package com.unlcn.ils.wms.backend.service.outbound.impl;

import cn.huiyunche.commons.domain.PageVo;
import cn.huiyunche.commons.exception.BusinessException;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import com.unlcn.ils.wms.backend.bo.baseDataBO.WmsWarehouseBO;
import com.unlcn.ils.wms.backend.bo.outboundBO.*;
import com.unlcn.ils.wms.backend.dto.outboundDTO.*;
import com.unlcn.ils.wms.backend.enums.*;
import com.unlcn.ils.wms.backend.service.baseData.WmsWarehouseService;
import com.unlcn.ils.wms.backend.service.borrow.WmsBorrowCarService;
import com.unlcn.ils.wms.backend.service.gate.GateControllerService;
import com.unlcn.ils.wms.backend.service.inbound.WmsInboundRepairService;
import com.unlcn.ils.wms.backend.service.inbound.WmsInventoryService;
import com.unlcn.ils.wms.backend.service.outbound.OutBoundTaskService;
import com.unlcn.ils.wms.backend.service.outbound.WmsPreparationPlanService;
import com.unlcn.ils.wms.backend.service.outbound.WmsShipmentPlanService;
import com.unlcn.ils.wms.backend.service.webservice.client.WmsJmCRMService;
import com.unlcn.ils.wms.backend.service.webservice.client.WmsJmDcsService;
import com.unlcn.ils.wms.backend.service.webservice.client.WmsJmSapService;
import com.unlcn.ils.wms.backend.util.*;
import com.unlcn.ils.wms.backend.util.jpush.JpushClientUtils;
import com.unlcn.ils.wms.base.businessDTO.outbound.WmsOutboundTaskDTO;
import com.unlcn.ils.wms.base.businessDTO.outbound.WmsOutboundTaskDTOForQuery;
import com.unlcn.ils.wms.base.dto.OutboundExcelDTO;
import com.unlcn.ils.wms.base.dto.WmsOutboundImportExcelDTO;
import com.unlcn.ils.wms.base.dto.WmsOutboundResultDTO;
import com.unlcn.ils.wms.base.mapper.additional.wmsOutbound.WmsOutboundTaskExtMapper;
import com.unlcn.ils.wms.base.mapper.extmapper.WmsHandoverOrderCustomMapper;
import com.unlcn.ils.wms.base.mapper.extmapper.WmsMailConfigExtMapper;
import com.unlcn.ils.wms.base.mapper.extmapper.WmsShipmentPlanExtMapper;
import com.unlcn.ils.wms.base.mapper.inbound.*;
import com.unlcn.ils.wms.base.mapper.junmadcs.WmsHandoverOrderExcpMapper;
import com.unlcn.ils.wms.base.mapper.junmadcs.WmsHandoverOrderMapper;
import com.unlcn.ils.wms.base.mapper.junmadcs.WmsOutOfStorageMapper;
import com.unlcn.ils.wms.base.mapper.outbound.WmsOutboundTaskMapper;
import com.unlcn.ils.wms.base.mapper.outbound.WmsPreparationPlanMapper;
import com.unlcn.ils.wms.base.mapper.outbound.WmsPreparationVehicleDetailMapper;
import com.unlcn.ils.wms.base.mapper.stock.*;
import com.unlcn.ils.wms.base.mapper.sys.SysUserMapper;
import com.unlcn.ils.wms.base.model.inbound.*;
import com.unlcn.ils.wms.base.model.junmadcs.*;
import com.unlcn.ils.wms.base.model.outbound.*;
import com.unlcn.ils.wms.base.model.stock.*;
import com.unlcn.ils.wms.base.model.sys.SysUser;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 出库信息的业务实现
 */
@Service
public class OutBoundTaskServiceImpl implements OutBoundTaskService {

    private Logger logger = LoggerFactory.getLogger(OutBoundTaskServiceImpl.class);

    private GateControllerService gateControllerService;

    @Autowired
    public void setGateControllerService(GateControllerService gateControllerService) {
        this.gateControllerService = gateControllerService;
    }

    private WmsJmCRMService wmsJmCRMService;

    @Autowired
    public void setWmsJmCRMService(WmsJmCRMService wmsJmCRMService) {
        this.wmsJmCRMService = wmsJmCRMService;
    }

    @Autowired
    private WmsOutboundTaskMapper wmsOutboundTaskMapper;

    @Autowired
    private WmsPreparationPlanMapper wmsPreparationPlanMapper;

    @Autowired
    private WmsOutboundTaskExtMapper outboundTaskExtMapper;

    @Autowired
    private WmsPreparationVehicleDetailMapper vehicleDetailMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private WmsInventoryLocationMapper wmsInventoryLocationMapper;//库存库位

    @Autowired
    private WmsInventoryMapper wmsInventoryMapper;//库存

    @Autowired
    private WmsInboundAllocationMapper wmsInboundAllocationMapper;

    @Autowired
    private WmsShipmentPlanService wmsShipmentPlanService;//发运计划

    @Autowired
    private WmsPreparationPlanService wmsPreparationPlanService;//备料详情

    @Autowired
    private WmsAsnTempMapper wmsAsnTempMapper;

    @Autowired
    private WmsBorrowCarService borrowCarService;//借车

    @Autowired
    private WmsInboundRepairService inboundRepairService;//维修

    @Autowired
    private WmsOutOfStorageMapper wmsOutOfStorageMapper;//出入库记录

    @Autowired
    private WmsJmDcsService wmsJmDcsService;//

    @Autowired
    private WmsJmSapService wmsJmSapService;

    @Autowired
    private WmsMailConfigExtMapper wmsMailConfigExtMapper;

    @Autowired
    private WmsShipmentPlanExtMapper wmsShipmentPlanExtMapper;

    @Autowired
    private WmsOutboundTaskExtMapper wmsOutboundTaskExtMapper;

    @Autowired
    private WmsShipmentPlanMapper shipmentPlanMapper;

    @Autowired
    private WmsInventoryService wmsInventoryService;//库存库位

    @Autowired
    private WmsInboundOrderMapper wmsInboundOrderMapper;

    @Autowired
    private WmsInboundOrderDetailMapper inboundOrderDetailMapper;

    @Autowired
    private WmsWarehouseService wmsWarehouseService;

    @Autowired
    private WmsPreparationVehicleDetailMapper wmsPreparationVehicleDetailMapper;

    @Autowired
    private WmsInboundRepairMapper wmsInboundRepairMapper;

    @Autowired
    private WmsBorrowCarDetailMapper wmsBorrowCarDetailMapper;

    @Autowired
    private WmsMailLogMapper wmsMailLogMapper;

    @Autowired
    private WmsHandoverOrderMapper wmsHandoverOrderMapper;

    @Autowired
    private WmsHandoverOrderExcpMapper wmsHandoverOrderExcpMapper;

    @Autowired
    private WmsHandoverOrderCustomMapper wmsHandoverOrderCustomMapper;

    @Autowired
    private WmsWarehouseNoticeDetailMapper wmsWarehouseNoticeDetailMapper;

    // 出库确认定时调度时间
    @Value("${wms.outbound.do.time}")
    private Integer WMS_OUTBOUND_DO_TIME;

    @Override
    public List<WmsPreparationPlanDTO> getOutboundTaskList(PageVo pageVo, WmsOutboundTaskBO wmsOutboundTaskBO) {
        logger.info("OutBoundTaskServiceImpl.getOutboundTaskList param : {}, {}", pageVo, wmsOutboundTaskBO);

        if (null == wmsOutboundTaskBO || null == wmsOutboundTaskBO.getOtWhCode()
                || StringUtils.isEmpty(wmsOutboundTaskBO.getOtWhCode())) {
            throw new IllegalArgumentException("仓库代码不能为空");
        }

        try {

            // 查询计划(按照创建时间)
            WmsPreparationPlanExample planExample = new WmsPreparationPlanExample();
            WmsPreparationPlanExample.Criteria planCriteria = planExample.createCriteria();
            planCriteria.andPpWhCodeEqualTo(wmsOutboundTaskBO.getOtWhCode());
            List<String> statusList = new ArrayList<>(2);
            statusList.add(String.valueOf(WmsPreparationPlanEnum.WMS_PLAN_START.getValue()));
            statusList.add(String.valueOf(WmsPreparationPlanEnum.WMS_PLAN_CONFIRM.getValue()));
            planCriteria.andPpStatusIn(statusList);
            planCriteria.andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue());
            planExample.setOrderByClause(" gmt_create desc");

            if (null != pageVo) {
                pageVo.setTotalRecord(wmsPreparationPlanMapper.countByExample(planExample));
                planExample.setLimitStart(pageVo.getStartIndex());
                planExample.setLimitEnd(pageVo.getPageSize());
            }

            List<WmsPreparationPlan> planList = wmsPreparationPlanMapper.selectByExample(planExample);
            List<WmsPreparationPlanDTO> resList = null;

            if (CollectionUtils.isNotEmpty(planList)) {
                resList = new ArrayList<>();
                for (WmsPreparationPlan plan : planList) {
                    WmsPreparationPlanDTO planDTO = new WmsPreparationPlanDTO();
                    BeanUtils.copyProperties(plan, planDTO);

                    WmsOutboundTaskExample example = new WmsOutboundTaskExample();
                    WmsOutboundTaskExample.Criteria criteria = example.createCriteria();
                    criteria.andOtWhCodeEqualTo(wmsOutboundTaskBO.getOtWhCode());
                    criteria.andOtStatusEqualTo(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_NEW.getValue() + "");
                    criteria.andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue());
                    criteria.andOtBlIdEqualTo(plan.getPpId() + "");
                    String orderByClause = " gmt_modify desc";
                    example.setOrderByClause(orderByClause);

                    // 查询任务
                    List<WmsOutboundTask> list = wmsOutboundTaskMapper.selectByExample(example);
                    List<AppWmsOutboundTaskListDTO> taskList = null;
                    if (CollectionUtils.isNotEmpty(list)) {
                        taskList = new ArrayList<>();
                        for (WmsOutboundTask wmsOutboundTask : list) {
                            //2018-4-9 任务界面增加库位展示
                            //AppWmsOutboundTaskListDTO appWmsOutboundTaskListDTO = new AppWmsOutboundTaskListDTO();
                            WmsOutboundTaskListForAppDTO appDTO = new WmsOutboundTaskListForAppDTO();
                            BeanUtils.copyProperties(wmsOutboundTask, appDTO);
                            appDTO.setOtLocCode(wmsOutboundTask.getOtLocationCode());
                            taskList.add(appDTO);
                        }
                        planDTO.setTaskList(taskList);
                        resList.add(planDTO);
                    }

                }
            }

            return resList;
        } catch (Exception e) {
            logger.error("OutBoundTaskServiceImpl.getOutboundTaskList error :", e);
            throw new BusinessException("获取数据异常");
        }
    }

    /**
     * 司机领取任务(重庆库/君马)
     * <p>
     * 2018-1-18 bugfix  调整有待完成任务的备料单  只对重庆库进行校验,君马库可能一车一单不进行校验
     * </p>
     *
     * @param wmsOutboundTaskBO 参数封装
     */
    @Override
    public void updateCompeteTask(WmsOutboundTaskBO wmsOutboundTaskBO) {
        logger.info("OutBoundTaskServiceImpl.updateCompeteTask param : {}", JSONObject.toJSONString(wmsOutboundTaskBO));
        if (null == wmsOutboundTaskBO || null == wmsOutboundTaskBO.getOtId() || wmsOutboundTaskBO.getOtId() < 1) {
            throw new IllegalArgumentException("参数不能为空");
        }

        // 是否有未完成的任务
        WmsOutboundTaskExample example = new WmsOutboundTaskExample();
        example.or().andOtDriverEqualTo(wmsOutboundTaskBO.getOtDriver())
                .andOtStatusEqualTo(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_READY.getValue() + "")
                .andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue());

        example.or().andOtDriverEqualTo(wmsOutboundTaskBO.getOtDriver())
                .andOtStatusEqualTo(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_GOING.getValue() + "")
                .andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue());

        int count = wmsOutboundTaskMapper.countByExample(example);
        if (count > 0) {
            throw new BusinessException("您有待完成的备料任务");
        }
        // 当前库区是否有未完成的备料单
        WmsOutboundTask wmsOutboundTask = wmsOutboundTaskMapper.selectByPrimaryKey(wmsOutboundTaskBO.getOtId());
        if (!Objects.equals(wmsOutboundTask, null) &&
                WhCodeEnum.UNLCN_XN_CQ.getValue().equals(wmsOutboundTask.getOtWhCode())) {
            String currentBlId = updateCurrentBlId(wmsOutboundTask.getOtWhCode());
            if (StringUtils.isNotBlank(currentBlId)) {
                if (!wmsOutboundTask.getOtBlId().equals(currentBlId)) {
                    throw new BusinessException("有待完成任务的备料单:" + currentBlId);
                }
            }
            //重庆库
            if (StringUtils.isNotBlank(wmsOutboundTask.getOtStatus()) &&
                    String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_CANCLE.getValue()).equals(wmsOutboundTask.getOtStatus())) {
                throw new BusinessException("该任务已经取消,请刷新任务页面");
            }
            WmsPreparationPlan plan = wmsPreparationPlanMapper.selectByPrimaryKey(Long.valueOf(wmsOutboundTask.getOtBlId()));
            if (String.valueOf(WmsPreparationPlanEnum.WMS_PLAN_START.getValue()).equals(plan.getPpStatus())) {
                plan.setModifyUserName(wmsOutboundTaskBO.getOtDriver());
                plan.setPpStatus(String.valueOf(WmsPreparationPlanEnum.WMS_PLAN_CONFIRM.getValue()));
                plan.setGmtUpdate(new Date());
                wmsPreparationPlanMapper.updateByPrimaryKeySelective(plan);
            }
        }
        try {

            //校验是否是在领取任务的过程中已取消的任务;如果是已经取消的任务,就再提示已取消
            wmsOutboundTask.setOtDriver(wmsOutboundTaskBO.getOtDriver());
            wmsOutboundTask.setOtStatus(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_READY.getValue() + "");
            wmsOutboundTask.setOtTaskStartTime(new Date());
            wmsOutboundTaskMapper.updateByPrimaryKey(wmsOutboundTask);
        } catch (BusinessException e) {
            logger.error("OutBoundTaskServiceImpl.updateCompeteTask error :", e);
            throw new BusinessException(e.getMessage());
        } catch (Exception e) {
            logger.error("OutBoundTaskServiceImpl.updateCompeteTask error :", e);
            throw new BusinessException("领取任务异常");
        }
    }

    @Override
    public String updateCurrentBlId(String whCode) {

        // 查询计划(按照创建时间)
        WmsPreparationPlanExample planExample = new WmsPreparationPlanExample();
        WmsPreparationPlanExample.Criteria planCriteria = planExample.createCriteria();
        planCriteria.andPpWhCodeEqualTo(whCode);
        planCriteria.andPpStatusEqualTo(WmsPreparationPlanEnum.WMS_PLAN_START.getValue() + "");
        planCriteria.andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue());
        planExample.setOrderByClause(" gmt_create ");

        List<WmsPreparationPlan> planList = wmsPreparationPlanMapper.selectByExample(planExample);

        if (CollectionUtils.isNotEmpty(planList)) {
            WmsPreparationPlan plan = planList.get(0);
            WmsOutboundTaskExample example = new WmsOutboundTaskExample();
            WmsOutboundTaskExample.Criteria criteria = example.createCriteria();
            criteria.andOtWhCodeEqualTo(whCode);
            criteria.andOtStatusEqualTo(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_NEW.getValue() + "");
            criteria.andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue());
            criteria.andOtBlIdEqualTo(plan.getPpId() + "");
            String orderByClause = " gmt_modify ";
            example.setOrderByClause(orderByClause);

            // 查询任务
            List<WmsOutboundTask> list = wmsOutboundTaskMapper.selectByExample(example);
            if (CollectionUtils.isNotEmpty(list)) {
                return list.get(0).getOtBlId();
            }
        }
        return null;
    }

    @Override
    public CurrentWmsOutboundTaskListDTO updateCurrentTask(WmsOutboundTaskBO wmsOutboundTaskBO) {
        logger.info("OutBoundTaskServiceImpl.updateCurrentTask param : {}", wmsOutboundTaskBO);

        if (null == wmsOutboundTaskBO || null == wmsOutboundTaskBO.getOtDriver()
                || StringUtils.isEmpty(wmsOutboundTaskBO.getOtDriver())) {
            throw new IllegalArgumentException("参数有误");
        }

        if (null == wmsOutboundTaskBO.getOtWhCode() || StringUtils.isEmpty(wmsOutboundTaskBO.getOtWhCode())) {
            throw new IllegalArgumentException("仓库代码参数不能为空");
        }

        try {
            WmsOutboundTaskExample example = new WmsOutboundTaskExample();
            example.or().andOtStatusEqualTo(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_READY.getValue() + "")
                    .andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue())
                    .andOtDriverEqualTo(wmsOutboundTaskBO.getOtDriver())
                    .andOtWhCodeEqualTo(wmsOutboundTaskBO.getOtWhCode());

            example.or().andOtStatusEqualTo(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_GOING.getValue() + "")
                    .andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue())
                    .andOtDriverEqualTo(wmsOutboundTaskBO.getOtDriver())
                    .andOtWhCodeEqualTo(wmsOutboundTaskBO.getOtWhCode());

            List<WmsOutboundTask> list = wmsOutboundTaskMapper.selectByExample(example);
            WmsOutboundTask wmsOutboundTask = null;
            if (CollectionUtils.isNotEmpty(list)) {
                wmsOutboundTask = list.get(0);
            }

            CurrentWmsOutboundTaskListDTO currentTask = null;
            if (null != wmsOutboundTask) {
                currentTask = new CurrentWmsOutboundTaskListDTO();
                BeanUtils.copyProperties(wmsOutboundTask, currentTask);
                currentTask.setOtLocationCode(wmsOutboundTask.getOtLocationCode());
                currentTask.setOtLcoationName(wmsOutboundTask.getOtLocationCode());
            }
            return currentTask;

        } catch (Exception e) {
            logger.error("OutBoundTaskServiceImpl.updateCurrentTask error :", e);
            throw new BusinessException("获取当前任务异常");
        }
    }

    @Override
    public List<CurrentWmsOutboundTaskListDTO> getFinishedTaskList(PageVo pageVo, WmsOutboundTaskBO wmsOutboundTaskBO) {
        logger.info("OutBoundTaskServiceImpl.getFinishedTaskList param : {}, {}", pageVo, wmsOutboundTaskBO);

        if (null == wmsOutboundTaskBO || null == wmsOutboundTaskBO.getOtDriver()
                || StringUtils.isEmpty(wmsOutboundTaskBO.getOtDriver())) {
            throw new IllegalArgumentException("参数有误");
        }

        if (null == wmsOutboundTaskBO.getOtWhCode() || StringUtils.isEmpty(wmsOutboundTaskBO.getOtWhCode())) {
            throw new IllegalArgumentException("仓库代码参数不能为空");
        }

        try {

            WmsOutboundTaskExample example = new WmsOutboundTaskExample();
            WmsOutboundTaskExample.Criteria criteria = example.createCriteria();
            criteria.andOtWhCodeEqualTo(wmsOutboundTaskBO.getOtWhCode());
            criteria.andOtStatusEqualTo(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue() + "");
            criteria.andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue());
            criteria.andOtDriverEqualTo(wmsOutboundTaskBO.getOtDriver());
            if (null != pageVo) {
                String orderByClause = StringUtils.isNotBlank(pageVo.getOrder()) ? pageVo.getOrder()
                        : " gmt_modify desc ";
                pageVo.setTotalRecord(wmsOutboundTaskMapper.countByExample(example));
                example.setOrderByClause(orderByClause);
                example.setLimitStart(pageVo.getStartIndex());
                example.setLimitEnd(pageVo.getPageSize());
            }

            List<WmsOutboundTask> list = wmsOutboundTaskMapper.selectByExample(example);
            List<CurrentWmsOutboundTaskListDTO> resList = null;
            if (CollectionUtils.isNotEmpty(list)) {
                resList = new ArrayList<>();
                for (WmsOutboundTask wmsOutboundTask : list) {
                    CurrentWmsOutboundTaskListDTO wmsOutboundTaskListDTO = new CurrentWmsOutboundTaskListDTO();
                    BeanUtils.copyProperties(wmsOutboundTask, wmsOutboundTaskListDTO);
                    wmsOutboundTaskListDTO.setOtLcoationName(wmsOutboundTask.getOtLocationCode());//code和name一样
                    wmsOutboundTaskListDTO.setOtLocationCode(wmsOutboundTask.getOtLocationCode());
                    resList.add(wmsOutboundTaskListDTO);
                }
            }
            return resList;

        } catch (Exception e) {
            logger.error("OutBoundTaskServiceImpl.getFinishedTaskList error :", e);
            throw new BusinessException("获取历史任务异常");
        }
    }

    /**
     * 出库作业管理列表查询
     *
     * @param wmsOutboundTaskFormBO 参数封装
     * @return 返回值
     */
    @Override
    public Map<String, Object> getOutboundTaskListForPage(WmsOutboundTaskFormBO wmsOutboundTaskFormBO) {
        logger.info("OutBoundTaskServiceImpl.getPreparateInfoByVin param: {}", wmsOutboundTaskFormBO);
        checkParam(wmsOutboundTaskFormBO);
        //搜索条件
        Map<String, Object> paramMap = getParamMap(wmsOutboundTaskFormBO, false);
        paramMap.put("hoHandoverNumber", wmsOutboundTaskFormBO.getHoHandoverNumber());
        paramMap.put("printStatus", wmsOutboundTaskFormBO.getPrintStatus());
        paramMap.put("printStartTime", wmsOutboundTaskFormBO.getPrintStartTime());
        paramMap.put("printEndTime", wmsOutboundTaskFormBO.getPrintEndTime());
        paramMap.put("otWhCode", wmsOutboundTaskFormBO.getOtWhCode());
        paramMap.put("otIsChange", TaskIsNeedChangeEnum.NO_CHANGE.getCode());//过来不需要换车的
        paramMap.put("isDeleted", DeleteFlagEnum.NORMAL.getValue());
        paramMap.put("limitStart", wmsOutboundTaskFormBO.getStartIndex());
        paramMap.put("limitEnd", wmsOutboundTaskFormBO.getPageSize());
        paramMap.put("orderByClause", " ot_id desc");
        if (wmsOutboundTaskFormBO.getOtQuitFlag() == null || wmsOutboundTaskFormBO.getOtQuitFlag() == 0) {
            paramMap.put("otQuitFlag", 0);
        } else {
            paramMap.put("otQuitFlag1", 1);
        }
        paramMap.put("otDriver", wmsOutboundTaskFormBO.getOtDriver());

        Map<String, Object> resultMap = new HashMap<>();
        PageVo pageVo = new PageVo();
        pageVo.setTotalRecord(outboundTaskExtMapper.countOutboundTasksForPage(paramMap));
        pageVo.setPageNo(wmsOutboundTaskFormBO.getStartIndex());
        pageVo.setPageSize(wmsOutboundTaskFormBO.getPageSize());
        List<WmsOutboundTaskDTO> outboundTaskDTOList = outboundTaskExtMapper.listOutboundTasksForPage(paramMap);
        //出库作业管理显示备料司机
        if (CollectionUtils.isNotEmpty(outboundTaskDTOList)) {
            outboundTaskDTOList.stream()
                    .filter(dto -> !Objects.equals(dto, null))
                    .forEach(dto -> {
                        if (StringUtils.isNotBlank(dto.getOtDriver()) && StringUtils.isNumeric(dto.getOtDriver())) {
                            SysUser sysUser = sysUserMapper.selectByPrimaryKey(Integer.parseInt(dto.getOtDriver()));
                            if (!Objects.equals(sysUser, null)) {
                                dto.setOtDriver(sysUser.getName());
                            }
                        }
                        //标记未打印状态
                        if (Objects.equals(dto.getPrintStatus(), null)) {
                            dto.setPrintStatus(0);
                        }
                    });
        }
        resultMap.put("dataList", outboundTaskDTOList);
        resultMap.put("page", pageVo);
        return resultMap;
    }

    /**
     * 交接单打印列表
     */
    @Override
    public Map<String, Object> getPrintOutboundTaskList(WmsOutboundTaskFormBO wmsOutboundTaskFormBO) {
        logger.info("OutBoundTaskServiceImpl.getPreparateInfoByVin param: {}", wmsOutboundTaskFormBO);
        checkParam(wmsOutboundTaskFormBO);
        //搜索条件
        Map<String, Object> paramMap = getParamMap(wmsOutboundTaskFormBO, false);
        paramMap.put("hoHandoverNumber", wmsOutboundTaskFormBO.getHoHandoverNumber());
        paramMap.put("hoHandoverNumberNotLike", OrderHeadEnum.BORROW.getCode() + "%");//过滤借车单
        if (wmsOutboundTaskFormBO.getPrintStatus() != null && wmsOutboundTaskFormBO.getPrintStatus() == 0) {
            paramMap.put("printStatusNoPrint", wmsOutboundTaskFormBO.getPrintStatus());
        } else {
            paramMap.put("printStatus", wmsOutboundTaskFormBO.getPrintStatus());
        }

        paramMap.put("printStartTime", wmsOutboundTaskFormBO.getPrintStartTime());
        paramMap.put("printEndTime", wmsOutboundTaskFormBO.getPrintEndTime());
        paramMap.put("otWhCode", wmsOutboundTaskFormBO.getOtWhCode());
        paramMap.put("otIsChange", TaskIsNeedChangeEnum.NO_CHANGE.getCode());//过来不需要换车的
        paramMap.put("isDeleted", DeleteFlagEnum.NORMAL.getValue());
        paramMap.put("limitStart", wmsOutboundTaskFormBO.getStartIndex());
        paramMap.put("limitEnd", wmsOutboundTaskFormBO.getPageSize());
        paramMap.put("orderByClause", " ot_id desc");
        paramMap.put("otQuitFlag", "0");

        Map<String, Object> resultMap = new HashMap<>();
        PageVo pageVo = new PageVo();
        //bugfix  2018-4-4 修复交接单打印界面查询未出库交接单数据
        pageVo.setTotalRecord(outboundTaskExtMapper.countOutboundTaskPrintForPage(paramMap));
        pageVo.setPageNo(wmsOutboundTaskFormBO.getStartIndex());
        pageVo.setPageSize(wmsOutboundTaskFormBO.getPageSize());
        //List<WmsOutboundTaskDTO> outboundTaskDTOList = outboundTaskExtMapper.listOutboundRecordsForPage(paramMap);
        //bugfix  2018-4-4 修复交接单打印界面查询未出库交接单数据
        List<WmsOutboundTaskDTO> outboundTaskDTOList = outboundTaskExtMapper.listOutboundTaskPrintForPage(paramMap);
        //出库作业管理显示备料司机
        if (CollectionUtils.isNotEmpty(outboundTaskDTOList)) {
            outboundTaskDTOList.stream()
                    .filter(dto -> !Objects.equals(dto, null))
                    .forEach(dto -> {
                        if (StringUtils.isNotBlank(dto.getOtDriver()) && StringUtils.isNumeric(dto.getOtDriver())) {
                            SysUser sysUser = sysUserMapper.selectByPrimaryKey(Integer.parseInt(dto.getOtDriver()));
                            if (!Objects.equals(sysUser, null)) {
                                dto.setOtDriver(sysUser.getName());
                            }
                        }
                        //标记未打印状态
                        if (Objects.equals(dto.getPrintStatus(), null)) {
                            dto.setPrintStatus(0);
                        }
                    });
        }
        resultMap.put("dataList", outboundTaskDTOList);
        resultMap.put("page", pageVo);
        return resultMap;
    }

    @Override
    public void updatePrintInfo(Long otId, Integer userId) {
        // 查询打印的信息
        WmsOutboundTask wmsOutboundTask = wmsOutboundTaskMapper.selectByPrimaryKey(otId);
        if (wmsOutboundTask == null)
            throw new BusinessException("找不到打印的信息!");

        //获取用户信息
        SysUser user = sysUserMapper.selectByPrimaryKey(userId);

        // 更新打印信息
        WmsOutboundTask updateTask = new WmsOutboundTask();
        updateTask.setOtId(otId);
        updateTask.setPrintStatus(1);
        updateTask.setPrintTime(new Date());
        updateTask.setPrintPerson(user.getName());
        Integer printNum = wmsOutboundTask.getPrintNum() == null ? 1 : wmsOutboundTask.getPrintNum() + 1;
        updateTask.setPrintNum(printNum);
        wmsOutboundTaskMapper.updateByPrimaryKeySelective(updateTask);
    }

    /**
     * 根据车架号查询对应的备料信息
     */
    @Override
    public WmsOutboundTaskDTO getPreparateInfoByVin(WmsOutboundTaskFormBO wmsOutboundTaskFormBO) {
        logger.info("OutBoundTaskServiceImpl.getPreparateInfoByVin param: {}", wmsOutboundTaskFormBO);
        checkParam(wmsOutboundTaskFormBO);
        if (StringUtils.isBlank(wmsOutboundTaskFormBO.getOtVin())) {
            throw new BusinessException("请输入车架号/底盘号");
        }
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("otVin", wmsOutboundTaskFormBO.getOtVin());
        List<WmsOutboundTaskDTO> wmsOutboundTaskDTOList = outboundTaskExtMapper.getPreparateInfoByVin(paramMap);
        if (CollectionUtils.isEmpty(wmsOutboundTaskDTOList)
                || wmsOutboundTaskDTOList.size() != 1) {
            throw new BusinessException("找不到对应的备料信息");
        }
        return wmsOutboundTaskDTOList.get(0);
    }

    /**
     * 根据备料单号查询对应的备料信息
     */
    @Override
    public List<WmsOutboundTaskDTO> getPreparateInfoByMaterialNo(WmsOutboundTaskFormBO wmsOutboundTaskFormBO) {
        logger.info("OutBoundTaskServiceImpl.getPreparateInfoByMaterialNo param: {}", wmsOutboundTaskFormBO);
        checkParam(wmsOutboundTaskFormBO);
        if (StringUtils.isBlank(wmsOutboundTaskFormBO.getOtPreparationMaterialNo())) {
            throw new BusinessException("请输入备料单号");
        }
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("otPreparationMaterialNo", wmsOutboundTaskFormBO.getOtPreparationMaterialNo());
        return outboundTaskExtMapper.getPreparateInfoByMaterialNo(paramMap);
    }

    /**
     * 根据车架号备料出库确认
     */
    @Override
    public void updateTaskToOutbound(WmsOutboundTaskFormBO wmsOutboundTaskFormBO) {
        logger.info("OutBoundTaskServiceImpl.updateTaskToOutbound param: {}", wmsOutboundTaskFormBO);
        checkParam(wmsOutboundTaskFormBO);
        if (StringUtils.isBlank(wmsOutboundTaskFormBO.getOtVin())) {
            throw new BusinessException("请输入车架号/底盘号");
        }
        //获取用户
        SysUser sysUser = null;
        if (StringUtils.isNotBlank(wmsOutboundTaskFormBO.getUserId()) && StringUtils.isNumeric(wmsOutboundTaskFormBO.getUserId())) {
            sysUser = sysUserMapper.selectByPrimaryKey(Integer.parseInt(wmsOutboundTaskFormBO.getUserId()));
        }
        //只对进行中的任务进行状态修改;
        WmsOutboundTaskExample taskExample = new WmsOutboundTaskExample();
        taskExample.createCriteria().andOtVinEqualTo(wmsOutboundTaskFormBO.getOtVin())
                .andOtStatusEqualTo(String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_GOING.getValue()));
        List<WmsOutboundTask> wmsOutboundTasks = wmsOutboundTaskMapper.selectByExample(taskExample);
        if (CollectionUtils.isEmpty(wmsOutboundTasks)) {
            throw new BusinessException("未查询到该车架号:" + wmsOutboundTaskFormBO.getOtVin() + "进行中的任务!");
        }
        WmsOutboundTask wmsOutboundTask = wmsOutboundTasks.get(0);
        if (wmsOutboundTask != null) {
            wmsOutboundTask.setOtStatus(String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue()));
            //备料完成时间
            wmsOutboundTask.setOtTaskEndTime(new Date());
            wmsOutboundTask.setGmtModify(new Date());
            if (sysUser != null) {
                wmsOutboundTask.setModifyUserId(String.valueOf(sysUser.getId()));
                wmsOutboundTask.setModifyUserName(sysUser.getName());//保存中文名
            }
            wmsOutboundTaskMapper.updateByPrimaryKeySelective(wmsOutboundTask);
            //释放库位,更新库存；
            WmsInventoryLocationExample inventoryLocationExample = new WmsInventoryLocationExample();
            WmsInventoryLocationExample.Criteria criteria = inventoryLocationExample.createCriteria();
            criteria.andInvlocVinEqualTo(wmsOutboundTaskFormBO.getOtVin());
            criteria.andIsDeletedNotEqualTo(DeleteFlagEnum.DELETED.getValue());
            List<WmsInventoryLocation> wmsInventoryLocations = wmsInventoryLocationMapper.selectByExample(inventoryLocationExample);
            if (CollectionUtils.isNotEmpty(wmsInventoryLocations)) {
                WmsInventoryLocation inventoryLocation = wmsInventoryLocations.get(0);
                if (StringUtils.isBlank(inventoryLocation.getInvlocLocCode()) || StringUtils.isBlank(inventoryLocation.getInvlocLocName())) {
                    throw new BusinessException("该车辆分配库位信息为空!");
                }
                if (sysUser != null) {
                    inventoryLocation.setModifyUserId(wmsOutboundTaskFormBO.getUserId());
                    inventoryLocation.setModifyUserName(sysUser.getName());
                }
                inventoryLocation.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
                inventoryLocation.setGmtUpdate(new Date());
                wmsInventoryLocationMapper.updateByPrimaryKeySelective(inventoryLocation);//逻辑删除
                //更新inventory库存
                WmsInventory wmsInventory = wmsInventoryMapper.selectByPrimaryKey(inventoryLocation.getInvlocInvId());
                if (!Objects.equals(wmsInventory, null)) {
                    wmsInventory.setGmtUpdate(new Date());
                    if (sysUser != null) {
                        wmsInventory.setModifyUserId(wmsOutboundTaskFormBO.getUserId());
                        wmsInventory.setModifyUserName(sysUser.getName());
                    }
                    wmsInventory.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
                    wmsInventoryMapper.updateByPrimaryKeySelective(wmsInventory);
                }
            }
            //逻辑删除入库库位分配表
            WmsInboundAllocationExample allocationExample = new WmsInboundAllocationExample();
            WmsInboundAllocationExample.Criteria allocationExampleCriteria = allocationExample.createCriteria();
            allocationExampleCriteria.andAlVinEqualTo(wmsOutboundTaskFormBO.getOtVin());
            allocationExampleCriteria.andIsDeletedNotEqualTo(DeleteFlagEnum.DELETED.getValue());
            List<WmsInboundAllocation> wmsInboundAllocations = wmsInboundAllocationMapper.selectByExample(allocationExample);
            if (CollectionUtils.isNotEmpty(wmsInboundAllocations)) {
                WmsInboundAllocation wmsInboundAllocation = wmsInboundAllocations.get(0);
                wmsInboundAllocation.setGmtUpdate(new Date());
                if (sysUser != null) {
                    wmsInboundAllocation.setModifyUserId(wmsOutboundTaskFormBO.getUserId());
                    wmsInboundAllocation.setModifyUserName(sysUser.getName());
                }
                wmsInboundAllocation.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
                wmsInboundAllocationMapper.updateByPrimaryKeySelective(wmsInboundAllocation);
            }
            //更新出库状态
            WmsPreparationVehicleDetailExample detailExample = new WmsPreparationVehicleDetailExample();
            detailExample.createCriteria().andVdVinEqualTo(wmsOutboundTaskFormBO.getOtVin());
            WmsPreparationVehicleDetail updateDeatail = new WmsPreparationVehicleDetail();
            if (sysUser != null) {
                updateDeatail.setModifyUserName(sysUser.getName());
            }
            updateDeatail.setVdOutstockStatus(String.valueOf(WmsOutboundStatusEnum.WMS_OUTBOUND_FINISH.getValue()));
            updateDeatail.setGmtUpdate(new Date());
            vehicleDetailMapper.updateByExampleSelective(updateDeatail, detailExample);
        }
    }

    @Override
    public void outboundToMail(String vin) {
        // 获取车架号发运信息
        List<WmsShipmentPlan> wmsShipmentPlanList = wmsShipmentPlanExtMapper.selectByVin(vin);
        if (CollectionUtils.isEmpty(wmsShipmentPlanList))
            return;
        WmsShipmentPlan wmsShipmentPlan = wmsShipmentPlanList.get(0);

        // 获取车架号的出库任务信息
        Map<String, Object> paramsMap = new HashMap<>();
        paramsMap.put("isDeleted", 1);
        paramsMap.put("otVin", vin);
        List<WmsOutboundTaskDTO> outboundTaskList = wmsOutboundTaskExtMapper.listOutboundRecordsForPage(paramsMap);
        if (CollectionUtils.isEmpty(outboundTaskList))
            return;
        WmsOutboundTaskDTO wmsOutboundTaskDTO = outboundTaskList.get(0);

        // 获取订单号
        String orderNo = (wmsShipmentPlan.getSpOrderNo() == null) ? "" : wmsShipmentPlan.getSpOrderNo();
        // DN号
        String waybillNo = (wmsShipmentPlan.getSpWaybillNo() == null) ? "" : wmsShipmentPlan.getSpWaybillNo();
        // 下单时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String orderDate = (wmsShipmentPlan.getGmtCreate() == null) ? "" : sdf.format(wmsShipmentPlan.getGmtCreate());
        // 出库仓库
        String whName = (wmsShipmentPlan.getSpWhName() == null) ? "" : wmsShipmentPlan.getSpWhName();
        // 出库人
        String outbounPerson = wmsOutboundTaskDTO.getModifyUserName();
        // 出库时间
        String outboundDate = sdf.format(new Date());
        // 经销商名称
        String dealerName = (wmsShipmentPlan.getSpDealerName() == null) ? "" : wmsShipmentPlan.getSpDealerName();
        // 货运地名称
        String detailedAddress = (wmsShipmentPlan.getSpDetailedAddress() == null) ? "" : wmsShipmentPlan.getSpDetailedAddress();

        // 获取邮件配置信息
        paramsMap = new HashMap<>();
        paramsMap.put("isDelete", 1);
        paramsMap.put("wmsMailType", 2);
        List<WmsMailConfig> mailConfigList = wmsMailConfigExtMapper.findParams(paramsMap);
        WmsMailConfig wmsMailConfig = mailConfigList.get(0);
        if (wmsMailConfig == null)
            return;

        // 邮件服务器
        String hostUrl = wmsMailConfig.getWmsHostUrl();
        // 用户名
        String user = wmsMailConfig.getWmsUserName();
        // 密码
        String pwd = wmsMailConfig.getWmsUserPwd();
        // 接收人
        String receipts = wmsMailConfig.getWmsReceipt();
        // 抄送人
        String ccs = wmsMailConfig.getWmsCc();
        // 邮件标题
        String title = wmsMailConfig.getWmsMailTitle();
        // 替换底盘号的占位符
        title = title.replaceAll("::vin::", vin);
        // 邮件内容
        String content = wmsMailConfig.getWmsSendTemplate();
        // 替换底盘号的占位符
        content = content.replaceAll("::vin::", vin);
        // 替换订单号的占位符
        content = content.replaceAll("::orderNo::", (orderNo == null) ? "" : orderNo);
        // 替换DN号的占位符
        content = content.replaceAll("::waybillNo::", (waybillNo == null) ? "" : waybillNo);
        // 替换下单时间的占位符
        content = content.replaceAll("::orderDate::", (orderDate == null) ? "" : orderDate);
        // 替换出库时间的占位符
        content = content.replaceAll("::outboundDate::", (outboundDate == null) ? "" : outboundDate);
        // 替换出库仓库的占位符
        content = content.replaceAll("::whName::", (whName == null) ? null : whName);
        // 替换出库人的占位符
        content = content.replaceAll("::outbounPerson::", (outbounPerson == null) ? "" : outbounPerson);
        // 替换经销商名称的占位符
        content = content.replaceAll("::dealerName::", (dealerName == null) ? "" : dealerName);
        // 替换货运地名称的占位符
        content = content.replaceAll("::detailedAddress::", (detailedAddress == null) ? "" : detailedAddress);

        // 发送邮件
        SendMail.sendMailMess(hostUrl, user, pwd, title, content, receipts, ccs);
    }

    /**
     * 根据固定时间点获取出库数据并发送邮件
     *
     * @param endTime 传入时间格式的字符串
     */
    @Override
    public void getOutboundSendMailDataNew(String startTime, String endTime) throws Exception {

        logger.info("OutBoundTaskServiceImpl.getOutboundSendMailDataNew param: {} {}", startTime, endTime);
        if (StringUtils.isBlank(endTime))
            throw new BusinessException("传入截止时间为空!");
        if (StringUtils.isBlank(startTime))
            throw new BusinessException("传入起始时间为空!");
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date endtimedate = null;
        try {
            endtimedate = format.parse(endTime);
        } catch (ParseException e) {
            throw new BusinessException("日期格式错误!");
        }
        SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat format3 = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
        //设置邮件数据起始时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        Date zero = calendar.getTime();
        String zeroTime = format.format(zero);  // --零点
        //1.先查询岂止时间段内是否有出库数据,有就发送邮件  没有就不发送邮件
        //byte del = DeleteFlagEnum.NOT_QUIT.getValue();
        //String whcode = WhCodeEnum.UNLCN_XN_CQ.getValue();
        //byte quit = TaskQuitFlagEnum.HAS_QUIT.getValue();
        //int cancleValue = WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue();
        List<OutboundExcelDTO> outboundExcelDTOS = wmsOutboundTaskExtMapper.outboundExcelData(startTime, endTime);
        if (CollectionUtils.isNotEmpty(outboundExcelDTOS)) {
            //发送时间段内邮件
            // 查询出库的车辆数--从零点到固定时间点所有的出库记录
            List<OutboundExcelDTO> outboundExcelDTOList = wmsOutboundTaskExtMapper.outboundExcelData(zeroTime, endTime);
            if (CollectionUtils.isNotEmpty(outboundExcelDTOList)) {
                int no = 1;
                for (OutboundExcelDTO outboundExcelDTO : outboundExcelDTOList) {
                    outboundExcelDTO.setNo(no);
                    Date taskEndTime = outboundExcelDTO.getTaskEndTime();
                    if (taskEndTime != null) {
                        String[] taskEndTimes = format.format(taskEndTime).split(" ");
                        outboundExcelDTO.setDate(taskEndTimes[0]);
                        outboundExcelDTO.setOutboundDate(taskEndTimes[1]);
                    }
                    //设置新增标识--重写equals方法
                    if (outboundExcelDTOS.contains(outboundExcelDTO)) {
                        outboundExcelDTO.setOrderFlag("新增订单");
                    }
                    no++;
                }

                // 获取当天生成的所有xls文件名称
                String filePath = Thread.currentThread().getContextClassLoader().getResource("").getPath();

                filePath = filePath + "outboundxls/";
                File directory = new File(filePath);
                if (!directory.exists()) {
                    directory.mkdirs();
                }
                //10点首次的时候 删除之前的文件
                //calendar.setTime(endtimedate);
                //int ten = calendar.get(Calendar.HOUR_OF_DAY);
                //首次执行
                if (outboundExcelDTOS.size() == outboundExcelDTOList.size()) {
                    // 删除昨天的所有文件
                    File[] files = new File(filePath).listFiles();
                    if (files != null && files.length > 0) {
                        for (File file : files) {
                            String fileName = file.getName();
                            file.delete();
                        }
                    }
                }

                // 获取目录下所有的文件
                List<String> nameList = getFileName(filePath);

                // 累加当天生成的所有xls
                String current = format2.format(new Date());
                if (CollectionUtils.isEmpty(nameList)) {
                    // 如果当天没有生成xls，则从一往上累加
                    filePath = filePath + current + "-1.xls";
                } else {
                    // 从一开始往上累加
                    Integer[] nums = new Integer[nameList.size()];
                    for (int i = 0; nameList.size() > i; i++) {
                        String name = nameList.get(i);
                        if (name.contains("-")) {
                            Integer num = Integer.valueOf(name.substring(name.lastIndexOf("-") + 1, name.indexOf(".")));
                            nums[i] = num;
                        } else {
                            nums[i] = 0;
                        }
                    }
                    Arrays.sort(nums);
                    int maxNum = 0;
                    if (nums.length != 0) {
                        maxNum = nums[nums.length - 1];
                    }
                    filePath = filePath + current + "-" + String.valueOf(maxNum + 1) + ".xls";
                }

                // 生成出库车辆的xls文件
                OutboundExcelUtils.export(outboundExcelDTOList, filePath);

                // 获取邮件配置信息
                Map<String, Object> paramsMap = new HashMap<>();
                paramsMap.put("isDelete", 1);
                paramsMap.put("wmsMailType", 2);
                List<WmsMailConfig> mailConfigList = wmsMailConfigExtMapper.findParams(paramsMap);
                WmsMailConfig wmsMailConfig = mailConfigList.get(0);
                if (wmsMailConfig == null)
                    return;

                // 邮件服务器
                String hostUrl = wmsMailConfig.getWmsHostUrl();
                // 用户名
                String user = wmsMailConfig.getWmsUserName();
                // 密码
                String pwd = wmsMailConfig.getWmsUserPwd();
                // 接收人
                String receipts = wmsMailConfig.getWmsReceipt();
                logger.info("邮件接收人：" + receipts);
                if (StringUtils.isEmpty(receipts)) {
                    return;
                }
                // 抄送人
                String ccs = wmsMailConfig.getWmsCc();

                // 邮件标题
                String title = "您好,请查收系统截止" + format3.format(endtimedate) + "出库记录";
                // 邮件内容
                String content = "您好,请查收系统截止" + format3.format(endtimedate) + "出库记录";
                // 发送邮件通知
                SendMail.sendMailHaveFile(hostUrl, user, pwd, title, content, receipts, ccs, filePath);
                //记录日志
                Runnable outMailLog = () -> {
                    WmsMailLog wmsMailLog = new WmsMailLog();
                    wmsMailLog.setGmtCreate(new Date());
                    wmsMailLog.setMailContent(new Gson().toJson(outboundExcelDTOList));
                    wmsMailLog.setReceiver(receipts);
                    wmsMailLog.setSendType(WmsGateControllerTypeEnum.GATE_OUT.getCode());
                    wmsMailLogMapper.insertSelective(wmsMailLog);
                };
                new Thread(outMailLog).start();
            }
        }
    }

    @Override
    public void getOutboundSendMailData() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat format3 = new SimpleDateFormat("yyyyMMdd HH:mm:ss");

        try {
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) - WMS_OUTBOUND_DO_TIME);
            String startTime = format.format(calendar.getTime());
            String endTime = format.format(new Date());
            // 查询出库的车辆数
            List<OutboundExcelDTO> outboundExcelDTOList = wmsOutboundTaskExtMapper.outboundExcelData(startTime, endTime);
            logger.info("起始时间：" + startTime);
            logger.info("创建时间：" + endTime);
            logger.info("出库的车辆数：" + outboundExcelDTOList.size());
            if (org.springframework.util.CollectionUtils.isEmpty(outboundExcelDTOList))
                return;
            // 查询当天所有出库车辆信息
            Calendar currCalendar = new GregorianCalendar();
            currCalendar.set(Calendar.HOUR_OF_DAY, 0);
            currCalendar.set(Calendar.MINUTE, 0);
            currCalendar.set(Calendar.SECOND, 0);
            startTime = format.format(currCalendar.getTime());
            outboundExcelDTOList = wmsOutboundTaskExtMapper.outboundExcelData(startTime, endTime);
            logger.info("起始时间：" + startTime);
            logger.info("创建时间：" + endTime);
            logger.info("当天所有出库车辆数：" + outboundExcelDTOList.size());
            if (org.springframework.util.CollectionUtils.isEmpty(outboundExcelDTOList))
                return;

            int no = 1;
            for (OutboundExcelDTO outboundExcelDTO : outboundExcelDTOList) {
                outboundExcelDTO.setNo(no);
                Date taskEndTime = outboundExcelDTO.getTaskEndTime();
                if (taskEndTime != null) {
                    String[] taskEndTimes = format.format(taskEndTime).split(" ");
                    outboundExcelDTO.setDate(taskEndTimes[0]);
                    outboundExcelDTO.setOutboundDate(taskEndTimes[1]);
                }
                no++;
            }

            // 获取当天生成的所有xls文件名称
            String filePath = Thread.currentThread().getContextClassLoader().getResource("").getPath();

            filePath = filePath + "outboundxls/";
            File directory = new File(filePath);
            if (!directory.exists()) {
                directory.mkdirs();
            }

            // 判断当前是否属于凌晨
            if ("00".equals(format.format(new Date()).substring(format.format(new Date()).indexOf(" ") + 1, format.format(new Date()).indexOf(" ") + 3))) {
                // 删除昨天的所有文件
                File[] files = new File(filePath).listFiles();
                for (File file : files) {
                    String fileName = file.getName();
                    file.delete();
                }
            }

            // 获取目录下所有的文件
            List<String> nameList = getFileName(filePath);

            // 累加当天生成的所有xls
            String current = format2.format(new Date());
            if (org.apache.commons.collections4.CollectionUtils.isEmpty(nameList)) {
                // 如果当天没有生成xls，则从一往上累加
                filePath = filePath + current + "-1.xls";
            } else {
                // 从一开始往上累加
                Integer[] nums = new Integer[nameList.size()];
                for (int i = 0; nameList.size() > i; i++) {
                    String name = nameList.get(i);
                    if (name.contains("-")) {
                        Integer num = Integer.valueOf(name.substring(name.lastIndexOf("-") + 1, name.indexOf(".")));
                        nums[i] = num;
                    } else {
                        nums[i] = 0;
                    }
                }
                Arrays.sort(nums);
                int maxNum = 0;
                if (nums.length != 0) {
                    maxNum = nums[nums.length - 1];
                }
                filePath = filePath + current + "-" + String.valueOf(maxNum + 1) + ".xls";
            }

            // 生成出库车辆的xls文件
            OutboundExcelUtils.export(outboundExcelDTOList, filePath);

            // 获取邮件配置信息
            Map<String, Object> paramsMap = new HashMap<String, Object>();
            paramsMap.put("isDelete", 1);
            paramsMap.put("wmsMailType", 2);
            List<WmsMailConfig> mailConfigList = wmsMailConfigExtMapper.findParams(paramsMap);
            WmsMailConfig wmsMailConfig = mailConfigList.get(0);
            if (wmsMailConfig == null)
                return;

            // 邮件服务器
            String hostUrl = wmsMailConfig.getWmsHostUrl();
            // 用户名
            String user = wmsMailConfig.getWmsUserName();
            // 密码
            String pwd = wmsMailConfig.getWmsUserPwd();
            // 接收人
            String receipts = wmsMailConfig.getWmsReceipt();
            logger.info("邮件接收人：" + receipts);
            if (StringUtils.isEmpty(receipts)) {
                return;
            }
            // 抄送人
            String ccs = wmsMailConfig.getWmsCc();

            // 邮件标题
            String title = "您好,请查收系统截止" + format3.format(new Date()) + "出库记录";
            // 邮件内容
            String content = "您好,请查收系统截止" + format3.format(new Date()) + "出库记录";
            // 发送邮件通知
            SendMail.sendMailHaveFile(hostUrl, user, pwd, title, content, receipts, ccs, filePath);
        } catch (Exception e) {
            logger.error("AsnOrderServiceImpl.inboundSendMailData error: {}", e);
        }
    }

    private List<String> getFileName(String path) {
        List<String> nameList = new ArrayList<String>();
        File f = new File(path);
        if (!f.exists()) {
            System.out.println(path + " not exists");
            return null;
        }
        File fa[] = f.listFiles();
        if (fa != null) {
            for (File fs : fa) {
                nameList.add(fs.getName());
            }
        }
        return nameList;
    }

    /**
     * 根据备料单号备料完成确认
     *
     * @param wmsOutboundTaskFormBO 参数封装
     */
    @Override
    public void updateTaskToConfirm(WmsOutboundTaskFormBO wmsOutboundTaskFormBO) {
        logger.info("OutBoundTaskServiceImpl.updateTaskToConfirm param: {}", wmsOutboundTaskFormBO);
        checkParam(wmsOutboundTaskFormBO);
        if (StringUtils.isBlank(wmsOutboundTaskFormBO.getOtPreparationMaterialNo())) {
            throw new BusinessException("请输入备料单号");
        }
        //备料单号 - 前置限制
        WmsOutboundTaskExample taskExample = new WmsOutboundTaskExample();
        taskExample.or().andOtPreparationMaterialNoEqualTo(wmsOutboundTaskFormBO.getOtPreparationMaterialNo())
                .andOtStatusNotEqualTo(String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_CANCLE.getValue()))
                .andIsDeletedNotEqualTo(DeleteFlagEnum.DELETED.getValue());
        taskExample.or().andOtPreparationMaterialNoEqualTo(wmsOutboundTaskFormBO.getOtPreparationMaterialNo())
                .andOtStatusNotEqualTo(String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_CANCLE.getValue()))
                .andIsDeletedIsNull();
        List<WmsOutboundTask> allCount = wmsOutboundTaskMapper.selectByExample(taskExample);
        if (CollectionUtils.isEmpty(allCount)) {
            throw new BusinessException("未查询到该备料单的备料任务,请确认");
        }
        String otBlId = allCount.get(0).getOtBlId();
        if (StringUtils.isNotBlank(otBlId)) {
            WmsPreparationPlan wmsPreparationPlan = wmsPreparationPlanMapper.selectByPrimaryKey(Long.valueOf(otBlId));
            if (String.valueOf(WmsPreparationPlanEnum.WMS_PLAN_FINISH.getValue())
                    .equals(wmsPreparationPlan.getPpStatus())) {
                throw new BusinessException("该备料单:" + otBlId + ",已进行该操作!");
            } else {
                if (!String.valueOf(WmsPreparationPlanEnum.WMS_PLAN_CONFIRM.getValue())
                        .equals(wmsPreparationPlan.getPpStatus())) {
                    throw new BusinessException("该备料单:" + otBlId + "未进行备料任务作业!");
                }
            }
        }
        WmsOutboundTaskExample outboundTaskExample = new WmsOutboundTaskExample();
        outboundTaskExample.or().andOtPreparationMaterialNoEqualTo(wmsOutboundTaskFormBO.getOtPreparationMaterialNo())
                .andOtStatusEqualTo(String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue()))
                .andIsDeletedNotEqualTo(DeleteFlagEnum.DELETED.getValue());
        outboundTaskExample.or().andOtPreparationMaterialNoEqualTo(wmsOutboundTaskFormBO.getOtPreparationMaterialNo())
                .andOtStatusNotEqualTo(String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue()))
                .andIsDeletedIsNull();

        List<WmsOutboundTask> finishedCount = wmsOutboundTaskMapper.selectByExample(outboundTaskExample);
        if (CollectionUtils.isNotEmpty(finishedCount) && allCount.size() != finishedCount.size()) {
            //不相等
            throw new BusinessException("该备料单存在未完成的任务");
        }
        //设置备料确认时间
        WmsOutboundTask outboundTask = new WmsOutboundTask();
        outboundTask.setOtBlConfirmTime(new Date());
        outboundTask.setGmtModify(new Date());
        wmsOutboundTaskMapper.updateByExampleSelective(outboundTask, outboundTaskExample);

        WmsPreparationPlan preparationPlan = new WmsPreparationPlan();
        preparationPlan.setPpStatus(String.valueOf(WmsPreparationPlanEnum.WMS_PLAN_FINISH.getValue()));
        preparationPlan.setGmtUpdate(new Date());
        WmsPreparationPlanExample planExample = new WmsPreparationPlanExample();
        planExample.createCriteria().andPpPreparationMaterialNoEqualTo(wmsOutboundTaskFormBO.getOtPreparationMaterialNo());
        wmsPreparationPlanMapper.updateByExampleSelective(preparationPlan, planExample);
    }

    /**
     * 出库记录查询-new
     * <p>
     * 出库记录查询页面增加“物料代码”、“配置”、“颜色代码”、“颜色”字段显示，导出的文件中也需要包含这四个字段
     * 2018-5-7  bugfix 修复君马库因换车后,出库记录查询及导出重复记录
     * 2018-5-17 出库记录增加物流商,便于统计物流商承运数
     * </p>
     *
     * @param bo 参数封装
     * @return 返回值
     */
    @Override
    public Map<String, Object> getOutboundRecordList(WmsOutboundRecordListBO bo) {
        logger.info("OutBoundTaskServiceImpl.getOutboundRecordList param: {}", bo);
        checkParam(bo);
        if (StringUtils.isBlank(bo.getOtWhCode())) {
            throw new BusinessException("仓库code不能为空!");
        }
        //搜索条件
        Map<String, Object> paramMap = getParamMap(bo, true);
        paramMap.put("otWhCode", bo.getOtWhCode());
        paramMap.put("otStatus", WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue());
        paramMap.put("limitStart", bo.getStartIndex());
        paramMap.put("limitEnd", bo.getPageSize());
        paramMap.put("notDel", DeleteFlagEnum.NORMAL.getValue());//过滤已删除
        paramMap.put("otQuitFlag", TaskQuitFlagEnum.NOT_QUIT.getValue());
        paramMap.put("otBlId", bo.getOtBlId());
        paramMap.put("orderByClause", "a.ot_id desc");
        //承运商
        if (StringUtils.isNotBlank(bo.getSpCarrier())) {
            paramMap.put("spCarrier", bo.getSpCarrier());
        }
        //经销商
        if (StringUtils.isNotBlank(bo.getSpDealer())) {
            paramMap.put("spDealer", bo.getSpDealer());
        }
        if (bo.getOtOutboundFlag() != null) {
            switch (bo.getOtOutboundFlag()) {
                case 0:
                    paramMap.put("otOutboundFlag", "(a.ot_outbound_flag = '0' or a.ot_outbound_flag is null)");
                    break;
                default:
                    paramMap.put("otOutboundFlag", "(a.ot_outbound_flag = '" + bo.getOtOutboundFlag() + "')");
                    break;
            }
        }

        String startBlConfirmTime = bo.getStartBlConfirmTime();
        if (StringUtils.isNotBlank(startBlConfirmTime)) {
            paramMap.put("startBlConfirmTime", startBlConfirmTime + " 00:00:00");
        }
        String endBlConfirmTime = bo.getEndBlConfirmTime();
        if (StringUtils.isNotBlank(endBlConfirmTime)) {
            paramMap.put("endBlConfirmTime", endBlConfirmTime + " 23:59:59");
        }

        if (StringUtils.isNotBlank(bo.getOtWhCode())) {
            if (WhCodeEnum.UNLCN_XN_CQ.getValue().equals(bo.getOtWhCode())) {
                Map<String, Object> resultMap = new HashMap<>();
                PageVo pageVo = new PageVo();
                paramMap.put("spNotDel", WmsShipmentPlanModifyTypeEnum.DELETE.getValue());
                pageVo.setTotalRecord(outboundTaskExtMapper.countOutboundRecordsByParamForCQ(paramMap));
                pageVo.setPageNo(bo.getPageNo());
                pageVo.setPageSize(bo.getPageSize());
                List<WmsOutboundTaskDTOForQuery> dtos = outboundTaskExtMapper.selectOutboundRecordsByParamForCQ(paramMap);
                //设置出库列表货主和出库确认人
                //ArrayList<WmsOutboundTaskDTOForQuery> list = updateCustomerNameAndOtherFieldsForCQ(dtos);
                if (CollectionUtils.isNotEmpty(dtos)) {
                    dtos.stream()
                            .filter(dto -> dto != null && StringUtils.isNotBlank(dto.getOtVin()))
                            .forEach((WmsOutboundTaskDTOForQuery dto) -> {
                                dto.setOtCustomerName(WmsCustomerEnum.CQ_JL.getName());
                            });
                }
                resultMap.put("dataList", dtos);
                resultMap.put("page", pageVo);
                return resultMap;
            }
            //君马库
            if (WhCodeEnum.JM_CS.getValue().equals(bo.getOtWhCode())
                    || WhCodeEnum.JM_XY.getValue().equals(bo.getOtWhCode())) {
                paramMap.put("atMaterialName", bo.getInventoryConfiguration());
                paramMap.put("materialCode", bo.getMaterialCode());
                Map<String, Object> resultMap = new HashMap<>();
                PageVo pageVo = new PageVo();
                //pageVo.setTotalRecord(outboundTaskExtMapper.countOutboundRecordsForPageJm(paramMap));
                // 2018-5-7  bugfix 修复君马库因换车后,出库记录查询及导出重复记录
                paramMap.put("notChange", TaskIsNeedChangeEnum.NO_CHANGE.getCode());
                paramMap.put("cantChange", TaskIsNeedChangeEnum.NOT_CAR_TO_CHANGE.getCode());
                outboundTaskExtMapper.updateSQLmode();
                pageVo.setTotalRecord(outboundTaskExtMapper.countOutboundRecordsForPageJmWithNotice(paramMap));
                pageVo.setPageNo(bo.getPageNo());
                pageVo.setPageSize(bo.getPageSize());
                //List<WmsOutboundTaskDTO> dtoList = outboundTaskExtMapper.listOutboundRecordsForPage(paramMap);
                //List<WmsOutboundTaskDTOForQuery> queries = outboundTaskExtMapper.listOutboundRecordsForPageJm(paramMap);
                List<WmsOutboundTaskDTOForQuery> queries = outboundTaskExtMapper.listOutboundRecordsForPageJmWithNotice(paramMap);
                //设置货主和其他字段补齐
                ArrayList<WmsOutboundTaskDTOForQuery> list = updateCustomerAndOtherFieldsForJM(queries);
                resultMap.put("dataList", list);
                resultMap.put("page", pageVo);
                return resultMap;
            }
        }
        return null;
    }

    /**
     * 设置客户和其他字段--jm仓库
     * <p>
     * 2018-1-23 君马出库记录查询页面增加“物料代码”、“配置”、“颜色代码”、“颜色”字段显示，导出的文件中也需要包含这四个字段
     * </p>
     *
     * @param queries 列表参数
     */
    private ArrayList<WmsOutboundTaskDTOForQuery> updateCustomerAndOtherFieldsForJM(List<WmsOutboundTaskDTOForQuery> queries) {
        ArrayList<WmsOutboundTaskDTOForQuery> list = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(queries)) {
            queries.stream()
                    .filter(dto -> dto != null && StringUtils.isNotBlank(dto.getOtVin()))
                    .forEach((WmsOutboundTaskDTOForQuery query) -> {
                        query.setOtDest(null);
                        query.setOtCustomerName(WmsCustomerEnum.JM.getName());
                        list.add(query);
                    });
        }
        return list;
    }

    /**
     * 为出库记录导出提取方法
     *
     * @param taskDTOS 参数封装
     * @return 返回值
     */
    private ArrayList<WmsOutboundTaskDTOForQuery> updateCustomerAndOtherFieldsForJMImport(List<WmsOutboundTaskDTO> taskDTOS) {
        ArrayList<WmsOutboundTaskDTOForQuery> list = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(taskDTOS)) {
            taskDTOS.stream()
                    .filter(dto -> dto != null && StringUtils.isNotBlank(dto.getOtVin()))
                    .forEach((WmsOutboundTaskDTO dto) -> {
                        WmsOutboundTaskDTOForQuery query = new WmsOutboundTaskDTOForQuery();
                        BeanUtils.copyProperties(dto, query);
                        query.setOtDest(null);
                        //先查备料详情表 车架号-->asn表数据  目的地--货主
                        WmsAsnTempExample example = new WmsAsnTempExample();
                        example.setOrderByClause("at_id desc");
                        example.setLimitStart(0);
                        example.setLimitEnd(1);
                        example.createCriteria().andAtVinEqualTo(dto.getOtVin());
                        List<WmsAsnTemp> wmsAsnTemps = wmsAsnTempMapper.selectByExample(example);
                        if (CollectionUtils.isNotEmpty(wmsAsnTemps)) {
                            WmsAsnTemp asnTemp = wmsAsnTemps.get(0);
                            query.setOtCustomerName(WmsCustomerEnum.JM.getName());
                            query.setMaterialCode(asnTemp.getAtMaterialCode());
                            query.setColourCode(asnTemp.getAtCarColourCode());
                            query.setColourName(asnTemp.getAtCarColour());
                            query.setConfiguration(asnTemp.getAtMaterialName());
                        }
                        //出库确认人  出库确认时间
                        list.add(query);
                    });
        }
        return list;

    }

    /**
     * 设置出库确认人和货主名称--重庆库
     *
     * @param dtoList 列表参数
     */
    private ArrayList<WmsOutboundTaskDTOForQuery> updateCustomerNameAndOtherFieldsForCQ(List<WmsOutboundTaskDTO> dtoList) {
        ArrayList<WmsOutboundTaskDTOForQuery> list = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(dtoList)) {
            dtoList.stream()
                    .filter(dto -> dto != null && StringUtils.isNotBlank(dto.getOtVin()))
                    .forEach((WmsOutboundTaskDTO dto) -> {
                        WmsOutboundTaskDTOForQuery query = new WmsOutboundTaskDTOForQuery();
                        BeanUtils.copyProperties(dto, query);
                        query.setOtCustomerName(WmsCustomerEnum.CQ_JL.getName());
                        //WmsShipmentPlanExample shipmentPlanExample = new WmsShipmentPlanExample();
                        //shipmentPlanExample.setLimitStart(0);
                        //shipmentPlanExample.setLimitEnd(1);
                        //shipmentPlanExample.setOrderByClause("sp_id desc");
                        //shipmentPlanExample.createCriteria().andSpVinEqualTo(dto.getOtVin())
                        //        .andSpSendBusinessFlagEqualTo(String.valueOf(SendBusinessFlagEnum.SEND_Y.getValue()));
                        //List<WmsShipmentPlan> planList = shipmentPlanMapper.selectByExample(shipmentPlanExample);
                        //if (CollectionUtils.isNotEmpty(planList)) {
                        //    WmsShipmentPlan shipmentPlan = planList.get(0);
                        //    if (shipmentPlan != null) {
                        //        query.setOtDest(shipmentPlan.getSpDest());
                        //        //设置货主
                        //        query.setOtCustomerName(shipmentPlan.getSpCustomerName());
                        //        //设置板车出库时间
                        //        //HashMap<String, Object> paramMap = Maps.newHashMap();
                        //        //paramMap.put("num", shipmentPlan.getSpSupplierVehiclePlate());
                        //        //paramMap.put("whCode", WhCodeEnum.UNLCN_XN_CQ.getValue());
                        //        //paramMap.put("shipNo", shipmentPlan.getSpDispatchNo());
                        //        //paramMap.put("out", WmsGateControllerTypeEnum.GATE_OUT.getCode());
                        //        //paramMap.put("opened", WmsDepartureOpenStatusEnum.OPENED.getValue());
                        //        //List<WmsDepartureRegister> registers = wmsDepartureRegisterExtMapper.selectDepartureOutTime(paramMap);
                        //        //if (CollectionUtils.isNotEmpty(registers)) {
                        //        //    query.setVehicleOutTime(registers.get(0).getDrDepartureTime());//板车出场时间
                        //        //}
                        //    }
                        //}
                        //出库确认人  --重庆库 不会更新状态
                        //if (dto.getOtBlConfirmTime() != null) {
                        //    WmsInventoryLocationExample locationExample = new WmsInventoryLocationExample();
                        //    locationExample.setOrderByClause(" gmt_update desc ");
                        //    locationExample.setLimitStart(0);
                        //    locationExample.setLimitEnd(1);
                        //    locationExample.createCriteria().andInvlocVinEqualTo(dto.getOtVin());
                        //    List<WmsInventoryLocation> wmsInventoryLocations = wmsInventoryLocationMapper.selectByExample(locationExample);
                        //    if (CollectionUtils.isNotEmpty(wmsInventoryLocations)) {
                        //        WmsInventoryLocation inventoryLocation = wmsInventoryLocations.get(0);
                        //        if (DeleteFlagEnum.DELETED.getValue() == inventoryLocation.getIsDeleted()) {
                        //            query.setModifyUserName(inventoryLocation.getModifyUserName());
                        //            query.setOtBlConfirmTime(inventoryLocation.getGmtUpdate());
                        //        }
                        //    }
                        //}
                        list.add(query);
                    });
        }
        return list;
    }

    /**
     * 根据车架号更改状态
     * 对比成功领取钥匙之后修改出库任务状态为30：进行中
     */
    @Override
    public void updateStatusByVin(String vin) {
        logger.info("OutBoundTaskServiceImpl.updateStatusByVinList param:{}", vin);
        WmsOutboundTaskExample wmsOutboundTaskExample = new WmsOutboundTaskExample();
        wmsOutboundTaskExample.or().andOtQuitFlagIsNull()
                .andOtVinEqualTo(vin)
                .andIsDeletedNotEqualTo(DeleteFlagEnum.DELETED.getValue())
                .andOtStatusNotEqualTo(String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_CANCLE.getValue()));
        wmsOutboundTaskExample.or().andOtQuitFlagEqualTo(TaskQuitFlagEnum.NOT_QUIT.getValue())
                .andOtVinEqualTo(vin)
                .andIsDeletedNotEqualTo(DeleteFlagEnum.DELETED.getValue())
                .andOtStatusNotEqualTo(String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_CANCLE.getValue()));
        List<WmsOutboundTask> allCount = wmsOutboundTaskMapper.selectByExample(wmsOutboundTaskExample);
        if (CollectionUtils.isEmpty(allCount)) {
            throw new BusinessException("未查询到车架号:" + vin + "的出库任务");
        }
        if (CollectionUtils.isNotEmpty(allCount)) {
            if (allCount.size() > 1) {
                throw new BusinessException("该车架号" + vin + "存在多条任务,请联系管理员");
            }

            WmsOutboundTask outboundTask = allCount.get(0);

            if (String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_NEW.getValue()).equals(outboundTask.getOtStatus())) {
                throw new BusinessException("该车架号:" + vin + "还未领取任务!");
            }
            if (String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_GOING.getValue()).equals(outboundTask.getOtStatus())
                    || String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue()).equals(outboundTask.getOtStatus())) {
                throw new BusinessException("该车架号:" + vin + "已经领取了钥匙,无需重复操作!");
            }
            outboundTask.setOtStatus(String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_GOING.getValue()));
            outboundTask.setGmtModify(new Date());
            wmsOutboundTaskMapper.updateByPrimaryKeySelective(outboundTask);

            // 推送消息到app
            JpushClientUtils.sendToAllAndroid2(outboundTask.getOtDriver(), "", 1003);
        }
    }

    /**
     * 任务取消 - 重庆库
     */
    @Override
    public void updateTaskToCancleForCq(WmsOutboundTaskFormBO outboundTaskFormBO) {
        logger.info("OutBoundTaskServiceImpl.updateTaskToCancleForCq outboundTaskFormBO: {}", outboundTaskFormBO);
        checkParam(outboundTaskFormBO);
        WmsOutboundTask outboundTask = checkForCancleAndQuit(outboundTaskFormBO);
        checkCancleForCq(outboundTask);
        //前置校验
        //WmsPreparationVehicleDetailExample detailExample = new WmsPreparationVehicleDetailExample();
        //detailExample.createCriteria().andVdVinEqualTo(outboundTask.getOtVin());
        //List<WmsPreparationVehicleDetail> detailList = vehicleDetailMapper.selectByExample(detailExample);
        //if (CollectionUtils.isNotEmpty(detailList)){
        //    WmsPreparationVehicleDetail detail = detailList.get(0);
        //    if (String.valueOf(WmsOutboundStatusEnum.WMS_OUTBOUND_FINISH.getValue()).equals(detail.getVdOutstockStatus())){
        //        throw new BusinessException("该任务计划已出库, 不可以取消");
        //    }
        //    detail.setIsDeleted(DeleteFlagEnum.NOT_QUIT.getValue());
        //    vehicleDetailMapper.updateByPrimaryKeySelective(detail);
        //}
        WmsPreparationVehicleDetail detail = checkDetailStatus(outboundTask.getOtVin(), "10");
        if (detail != null) {
            detail.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
            vehicleDetailMapper.updateByPrimaryKeySelective(detail);
        }
        //更新状态 - WmsOutboundTaskStatusEnum
        outboundTask.setOtStatus(String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_CANCLE.getValue()));
        outboundTask.setCancleReason(outboundTaskFormBO.getCancleReason());
        outboundTask.setGmtModify(new Date());
        wmsOutboundTaskMapper.updateByPrimaryKeySelective(outboundTask);

        //判断备料单号
        if (StringUtils.isNotBlank(outboundTask.getOtPreparationMaterialNo())) {

            WmsOutboundTaskExample selectTaskExample = new WmsOutboundTaskExample();
            WmsOutboundTaskExample.Criteria criteria = selectTaskExample.createCriteria();
            criteria.andOtPreparationMaterialNoEqualTo(outboundTask.getOtPreparationMaterialNo());
            int allCount = wmsOutboundTaskMapper.countByExample(selectTaskExample);

            criteria.andOtStatusEqualTo(String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_CANCLE.getValue()));
            int statusCount = wmsOutboundTaskMapper.countByExample(selectTaskExample);
            //同一个备料编号下的任务都已经取消
            if (allCount == statusCount) {

                WmsPreparationPlan updatePlan = new WmsPreparationPlan();
                updatePlan.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
                updatePlan.setGmtUpdate(new Date());

                WmsPreparationPlanExample planExample = new WmsPreparationPlanExample();
                planExample.createCriteria()
                        .andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue())
                        .andPpPreparationMaterialNoEqualTo(outboundTask.getOtPreparationMaterialNo());
                wmsPreparationPlanMapper.updateByExampleSelective(updatePlan, planExample);
            }
        }
    }

    /**
     * 备料退库
     */
    @Override
    public void updateTaskToQuitForCq(WmsOutboundTaskFormBO outboundTaskFormBO) {
        logger.info("OutBoundTaskServiceImpl.updateTaskToCancleForCq outboundTaskFormBO: {}", outboundTaskFormBO);
        checkParam(outboundTaskFormBO);
        WmsOutboundTask outboundTask = checkForCancleAndQuit(outboundTaskFormBO);
        checkQuitForCq(outboundTask);
        //备料详情校验
        WmsPreparationVehicleDetail detail = checkDetailStatus(outboundTask.getOtVin(), "20");
        if (detail != null) {
            detail.setVdOutstockStatus(String.valueOf(WmsOutboundStatusEnum.WMS_OUTBOUND_QUIT.getValue()));
            vehicleDetailMapper.updateByPrimaryKeySelective(detail);
        }
        //更新未已退库
        outboundTask.setOtQuitFlag(TaskQuitFlagEnum.HAS_QUIT.getValue());
        outboundTask.setOtRemark(outboundTaskFormBO.getCancleReason());
        //更新任务为已删除,修复app扫描报错
        //outboundTask.setIsDeleted(DeleteFlagEnum.NOT_QUIT.getValue());
        wmsOutboundTaskMapper.updateByPrimaryKeySelective(outboundTask);

        //获取老入库记录
        WmsInboundOrder oldInboundOrder = getOldInboundOrder(outboundTask.getOtVin());
        if (oldInboundOrder == null) {
            throw new BusinessException("该单没有入库记录, 请核实");
        }
        WmsInboundOrderDetailExample detailExample = new WmsInboundOrderDetailExample();
        detailExample.createCriteria().andOddOdIdEqualTo(oldInboundOrder.getOdId());
        List<WmsInboundOrderDetail> orderDetailList = inboundOrderDetailMapper.selectByExample(detailExample);
        if (CollectionUtils.isEmpty(orderDetailList)) {
            throw new BusinessException("该单没有入库记录, 请核实");
        }

        WmsInboundOrderDetail inboundOrderDetail = orderDetailList.get(0);

        WmsWarehouse warehouse = getWarehouse(outboundTaskFormBO.getOtWhCode());

        //生成入库单wmsWarehouseService
        WmsInboundOrder insertOrder = new WmsInboundOrder();
        BeanUtils.copyProperties(oldInboundOrder, insertOrder);
        reSetOrderInfo(insertOrder);
        if (warehouse != null) {
            insertOrder.setOdWhCode(warehouse.getWhCode());
            insertOrder.setOdWhName(warehouse.getWhName());
            insertOrder.setOdWhId(warehouse.getWhId());
        }
        wmsInboundOrderMapper.insertSelective(insertOrder);
        //入库详情
        WmsInboundOrderDetail insertDetail = new WmsInboundOrderDetail();
        BeanUtils.copyProperties(inboundOrderDetail, insertDetail);
        insertDetail.setOddOdId(insertOrder.getOdId());
        reSetOrderDetailInfo(insertDetail);
        if (warehouse != null) {
            insertDetail.setOddWhCode(warehouse.getWhCode());
            insertDetail.setOddWhName(warehouse.getWhName());
        }
        inboundOrderDetailMapper.insertSelective(insertDetail);

        //将detail和order更新为逻辑已删除
        inboundOrderDetail.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
        inboundOrderDetail.setGmtUpdate(new Date());
        inboundOrderDetailMapper.updateByPrimaryKeySelective(inboundOrderDetail);
        //WmsInboundOrder wmsInboundOrder = wmsInboundOrderMapper.selectByPrimaryKey(inboundOrderDetail.getOddOdId());
        if (!Objects.equals(oldInboundOrder, null)) {
            oldInboundOrder.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
            oldInboundOrder.setGmtUpdate(new Date());
            wmsInboundOrderMapper.updateByPrimaryKeySelective(oldInboundOrder);
        }
    }

    /**
     * 清空入库信息
     */
    private void reSetOrderInfo(WmsInboundOrder insertOrder) {

        //insertOrder.setInspectStatus(TmsInspectStatusEnum.WAYBILL_INIT.getValue());
        insertOrder.setGmtCreate(new Date());
        insertOrder.setGmtUpdate(new Date());
        //insertOrder.setOdBusinessType("");
        //insertOrder.setIsDeleted(DeleteFlagEnum.HAS_QUIT.getValue());//逻辑删除是正常
        insertOrder.setOdStatus(String.valueOf(WmsInboundStatusEnum.WMS_INBOUND_CREATE.getValue()));
        //insertOrder.setOdCheckResult(null);//检验结果
        //insertOrder.setOdCheckDesc(null);//检验描述
        //insertOrder.setOdConsigneeDate(null);//收货日期
        insertOrder.setOdWaybillType(WmsSysSourceEnum.WMS_QUIT.getValue());
        insertOrder.setIsDeleted(DeleteFlagEnum.NORMAL.getValue());
    }

    /**
     * 清空入库详情信息
     */
    private void reSetOrderDetailInfo(WmsInboundOrderDetail insertDetail) {
        insertDetail.setGmtUpdate(new Date());
        //清空库位库存
        insertDetail.setOddWhLocName(null);
        insertDetail.setOddWhLocCode(null);
        insertDetail.setOddWhZoneCode(null);
        insertDetail.setOddWhZoneName(null);
        //insertDetail.setoddo
        insertDetail.setIsDeleted(DeleteFlagEnum.NORMAL.getValue());//逻辑删除是正常
    }

    private WmsWarehouse getWarehouse(String code) {
        if (StringUtils.isNotBlank(code)) {
            WmsWarehouseBO wmsWarehouseBO = new WmsWarehouseBO();
            wmsWarehouseBO.setWhCode(code);
            return wmsWarehouseService.findWarehouseByCode(wmsWarehouseBO);
        }
        return null;
    }

    /**
     * 获取老入库记录
     */
    private WmsInboundOrder getOldInboundOrder(String vin) {
        if (StringUtils.isNotBlank(vin)) {

            WmsInboundOrderDetailExample detailExample = new WmsInboundOrderDetailExample();
            detailExample.createCriteria().andOddVinEqualTo(vin);
            List<WmsInboundOrderDetail> detailList = inboundOrderDetailMapper.selectByExample(detailExample);
            if (CollectionUtils.isEmpty(detailList)) {
                throw new BusinessException("该单没有入库记录, 请核实");
            }

            List<Long> orderIdList = new ArrayList<>();
            detailList.stream()
                    .filter(detail -> detail != null && detail.getOddOdId() != null)
                    .forEach(detail -> orderIdList.add(detail.getOddOdId()));

            if (CollectionUtils.isEmpty(orderIdList)) {
                throw new BusinessException("该单没有入库记录, 请核实");
            }

            WmsInboundOrderExample example = new WmsInboundOrderExample();
            example.setOrderByClause(" od_id desc ");
            example.createCriteria()
                    .andOdIdIn(orderIdList)
                    .andOdWaybillTypeEqualTo(WmsSysSourceEnum.TMS.getValue());
            List<WmsInboundOrder> orderList = wmsInboundOrderMapper.selectByExample(example);
            if (CollectionUtils.isEmpty(orderList)) {
                throw new BusinessException("该单没有入库记录, 请核实");
            }

            return orderList.get(0);
        }
        return null;
    }

    /**
     * 状态校验
     */
    private WmsPreparationVehicleDetail checkDetailStatus(String vin, String status) {
        if (StringUtils.isNotBlank(vin) && StringUtils.isNotBlank(status)) {
            //前置校验
            WmsPreparationVehicleDetailExample detailExample = new WmsPreparationVehicleDetailExample();
            detailExample.createCriteria().andVdVinEqualTo(vin);
            List<WmsPreparationVehicleDetail> detailList = vehicleDetailMapper.selectByExample(detailExample);
            if (CollectionUtils.isNotEmpty(detailList)) {
                WmsPreparationVehicleDetail detail = detailList.get(0);
                //取消任务
                if ("10".equals(status)) {
                    if (String.valueOf(WmsOutboundStatusEnum.WMS_OUTBOUND_FINISH.getValue()).equals(detail.getVdOutstockStatus())) {
                        throw new BusinessException("该任务计划已出库, 不可取消");
                    }
                }
                //备料退库
                if ("20".equals(status)) {
                    if (!String.valueOf(WmsOutboundStatusEnum.WMS_OUTBOUND_FINISH.getValue()).equals(detail.getVdOutstockStatus())) {
                        throw new BusinessException("该任务计划未出库, 不可退库");
                    }
                }
                return detail;
            }
        }
        return null;
    }

    /**
     * 参数校验
     */
    private void checkParam(WmsOutboundTaskFormBO wmsOutboundTaskFormBO) {
        if (Objects.equals(wmsOutboundTaskFormBO, null)) {
            throw new BusinessException("参数为空");
        }
    }

    /**
     * 校验
     */
    private WmsOutboundTask checkForCancleAndQuit(WmsOutboundTaskFormBO outboundTaskFormBO) {
        if (outboundTaskFormBO.getOtId() == null) {
            throw new BusinessException("没有选择指定任务");
        }
        WmsOutboundTask outboundTask = wmsOutboundTaskMapper.selectByPrimaryKey(outboundTaskFormBO.getOtId());
        if (outboundTask == null) {
            throw new BusinessException("找不到对应的任务");
        }
        return outboundTask;
    }

    /**
     * 任务取消的前置校验
     */
    private void checkCancleForCq(WmsOutboundTask outboundTask) {
        if (String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_GOING.getValue()).equals(outboundTask.getOtStatus())
                || String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue()).equals(outboundTask.getOtStatus())
                || String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_CANCLE.getValue()).equals(outboundTask.getOtStatus())) {
            throw new BusinessException("该任务状态为进行中/已完成, 不可取消");
        }
    }

    /**
     * 任务取消的前置校验
     */
    private void checkQuitForCq(WmsOutboundTask outboundTask) {

        if (!String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue()).equals(outboundTask.getOtStatus())) {
            throw new BusinessException("该任务未完成, 不可退库");
        }
    }

    /**
     * 搜索条件
     */
    private Map<String, Object> getParamMap(WmsOutboundTaskFormBO bo, boolean isRecord) {
        Map<String, Object> paramMap = new HashMap<>();
        Date date = null;
        //车架号
        if (StringUtils.isNotBlank(bo.getOtVin())) {
            paramMap.put("otVin", bo.getOtVin());
        }
        //车型
        if (StringUtils.isNotBlank(bo.getOtVehicleSpecName())) {
            paramMap.put("otVehicleSpecName", bo.getOtVehicleSpecName());
        }
        //备料确认时间
        if (StringUtils.isNotBlank(bo.getStartBlConfirmTime())) {
            date = DateUtils.StrToDate(bo.getStartBlConfirmTime(), DateUtils.YYYY_MM_DD);
            if (date != null) {
                paramMap.put("startBlConfirmTime", date);
            }
            date = null;
        }
        if (StringUtils.isNotBlank(bo.getEndBlConfirmTime())) {
            date = DateUtils.StrToDate(bo.getEndBlConfirmTime(), DateUtils.YYYY_MM_DD);
            if (date != null) {
                date.setTime(date.getTime() + (24 * 60 * 60 * 1000));
                paramMap.put("endBlConfirmTime", date);
            }
            date = null;
        }
        //如果是出库记录查询
        if (isRecord) {
            return paramMap;
        }
        //备料单号
        if (StringUtils.isNotBlank(bo.getOtPreparationMaterialNo())) {
            paramMap.put("otPreparationMaterialNo", bo.getOtPreparationMaterialNo());
        }
        //装车道
        if (StringUtils.isNotBlank(bo.getOtEstimateLane())) {
            paramMap.put("otEstimateLane", bo.getOtEstimateLane());
        }
        //状态
        if (StringUtils.isNotBlank(bo.getOtStatus())) {
            paramMap.put("otStatus", bo.getOtStatus());
        } else {
            paramMap.put("otStatusNotEquals", String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_CANCLE.getValue()));
        }

        //创建时间
        if (StringUtils.isNotBlank(bo.getStartCreateTime())) {
            date = DateUtils.StrToDate(bo.getStartCreateTime(), DateUtils.YYYY_MM_DD);
            if (date != null) {
                paramMap.put("startCreateTime", date);
            }
            date = null;
        }
        if (StringUtils.isNotBlank(bo.getEndCreateTime())) {
            date = DateUtils.StrToDate(bo.getEndCreateTime(), DateUtils.YYYY_MM_DD);
            if (date != null) {
                date.setTime(date.getTime() + (24 * 60 * 60 * 1000));
                paramMap.put("endCreateTime", date);
            }
            date = null;
        }

        return paramMap;
    }

    /**
     * 开始任务/完成任务--君马
     * <p>
     * 说明: bo中status参数传入30 表示领取任务  40 表示完成任务
     * 2018-1-18  bugfix状态校验:最后一个任务的完成时候 写入整个交接单下的任务备料确认时间
     * 2018-5-9 bugfix 状态校验,app可能传入领取完成任务的车辆实际已经被别的司机领取任务完成..
     * </p>
     */
    @Override
    public void saveStartOrFinishTask(OutboundTaskStartBO bo) {
        logger.info("OutBoundTaskServiceImpl.saveStartOrFinishTask param : {}", bo);
        if (null == bo) {
            throw new IllegalArgumentException("参数不能为空");
        }

        if (null == bo.getTaskId() || bo.getTaskId() < 1) {
            throw new IllegalArgumentException("当前任务号为空");
        }

        if (null == bo.getVin() || StringUtils.isEmpty(bo.getVin())) {
            throw new IllegalArgumentException("请扫描车架号");
        }

        if (null == bo.getStatus() || StringUtils.isEmpty(bo.getStatus())) {
            throw new IllegalArgumentException("参数状态有误");
        }

        if (!bo.getStatus().equals(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_GOING.getValue() + "")
                && !bo.getStatus().equals(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue() + "")) {
            throw new IllegalArgumentException("当前任务不支持该操作");
        }

        // 当前任务是否可以开始
        WmsOutboundTask task = wmsOutboundTaskMapper.selectByPrimaryKey(bo.getTaskId());

        if (null == task || task.getOtId() < 1) {
            throw new BusinessException("当前任务无效");
        }

        if (bo.getStatus().equals(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_GOING.getValue() + "")) {
            if (!task.getOtStatus().equals(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_READY.getValue() + "")) {
                throw new BusinessException("当前任务状态不支持操作");
            }
        }

        if (bo.getStatus().equals(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue() + "")) {
            if (!task.getOtStatus().equals(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_GOING.getValue() + "")) {
                throw new BusinessException("当前任务状态不支持操作");
            }
        }

        if (!task.getOtVin().equals(bo.getVin().trim())) {
            throw new BusinessException("车架号不匹配");
        }

        task.setOtStatus(bo.getStatus());
        //如果是已完成备料出库，需要释放库位
        if (Objects.equals(bo.getStatus(), String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue()))) {
            //更新备料详情为已出库
            updateDetailToOut(task.getOtVin(), task);
            //任务完成时间
            task.setOtTaskEndTime(new Date());

            //释放库位,更新库存
            WmsInventoryLocationExample inventoryLocationExample = new WmsInventoryLocationExample();
            WmsInventoryLocationExample.Criteria criteria = inventoryLocationExample.createCriteria();
            criteria.andInvlocVinEqualTo(bo.getVin());
            criteria.andIsDeletedNotEqualTo(DeleteFlagEnum.DELETED.getValue());
            List<WmsInventoryLocation> wmsInventoryLocations = wmsInventoryLocationMapper.selectByExample(inventoryLocationExample);
            if (CollectionUtils.isNotEmpty(wmsInventoryLocations)) {
                WmsInventoryLocation inventoryLocation = wmsInventoryLocations.get(0);
                //if (StringUtils.isBlank(inventoryLocation.getInvlocLocCode()) || StringUtils.isBlank(inventoryLocation.getInvlocLocName())) {
                //    throw new BusinessException("该车辆分配库位信息为空!");
                //}
                if (StringUtils.isBlank(inventoryLocation.getInvlocLocCode())) {
                    throw new BusinessException("该车辆分配库位信息为空!");
                }
                //君马库释放库位将库位信息设置为空,不逻辑删除
                inventoryLocation.setInvlocZoneId(null);
                inventoryLocation.setInvlocZoneName(null);
                inventoryLocation.setInvlocZoneCode(null);
                inventoryLocation.setInvlocLocId(null);
                inventoryLocation.setInvlocLocCode(null);
                inventoryLocation.setInvlocLocName(null);
                inventoryLocation.setGmtUpdate(new Date());

                wmsInventoryLocationMapper.updateByPrimaryKey(inventoryLocation);
                //更新inventory库存
                //WmsInventory wmsInventory = wmsInventoryMapper.selectByPrimaryKey(inventoryLocation.getInvlocInvId());
                //if (!Objects.equals(wmsInventory, null)) {
                //    wmsInventory.setIsDeleted(DeleteFlagEnum.NOT_QUIT.getValue());
                //    wmsInventoryMapper.updateByPrimaryKeySelective(wmsInventory);
                //}
            }
            //逻辑删除入库库位分配表
            WmsInboundAllocationExample allocationExample = new WmsInboundAllocationExample();
            WmsInboundAllocationExample.Criteria allocationExampleCriteria = allocationExample.createCriteria();
            allocationExampleCriteria.andAlVinEqualTo(bo.getVin());
            allocationExampleCriteria.andIsDeletedNotEqualTo(DeleteFlagEnum.DELETED.getValue());
            List<WmsInboundAllocation> wmsInboundAllocations = wmsInboundAllocationMapper.selectByExample(allocationExample);
            if (CollectionUtils.isNotEmpty(wmsInboundAllocations)) {
                WmsInboundAllocation wmsInboundAllocation = wmsInboundAllocations.get(0);
                wmsInboundAllocation.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
                wmsInboundAllocation.setGmtUpdate(new Date());
                wmsInboundAllocationMapper.updateByPrimaryKeySelective(wmsInboundAllocation);
            }
        } else if (Objects.equals(bo.getStatus(), String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_GOING.getValue()))) {
            //任务开始时间
            task.setOtTaskStartTime(new Date());
            updatePrepareStatus(task.getOtVin(), task);
        }
        wmsOutboundTaskMapper.updateByPrimaryKey(task);

    }

    /**
     * 更新备料详情为已出库
     *
     * @param vin             车架号
     * @param wmsOutboundTask 出库任务
     */
    private void updateDetailToOut(String vin, WmsOutboundTask wmsOutboundTask) {
        if (StringUtils.isNotBlank(vin)) {
            WmsPreparationVehicleDetailExample detailExample = new WmsPreparationVehicleDetailExample();
            detailExample.setOrderByClause(" vd_id desc ");
            detailExample.createCriteria()
                    .andVdVinEqualTo(vin)
                    .andVdPpIdEqualTo(Long.valueOf(wmsOutboundTask.getOtBlId()))
                    .andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue());
            List<WmsPreparationVehicleDetail> detailList = vehicleDetailMapper.selectByExample(detailExample);
            if (CollectionUtils.isNotEmpty(detailList)) {
                WmsPreparationVehicleDetail detail = detailList.get(0);
                detail.setVdOutstockStatus(String.valueOf(WmsOutboundStatusEnum.WMS_OUTBOUND_FINISH.getValue()));
                detail.setGmtUpdate(new Date());
                vehicleDetailMapper.updateByPrimaryKeySelective(detail);

                //判断这个备料计划下的数据是否已经完成
                WmsPreparationVehicleDetailExample selectExample = new WmsPreparationVehicleDetailExample();
                WmsPreparationVehicleDetailExample.Criteria criteria = selectExample.createCriteria();
                criteria.andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue());
                criteria.andVdPpIdEqualTo(detail.getVdPpId());

                int allCount = vehicleDetailMapper.countByExample(selectExample);

                criteria.andVdOutstockStatusEqualTo(String.valueOf(WmsOutboundStatusEnum.WMS_OUTBOUND_FINISH.getValue()));
                int statueCount = vehicleDetailMapper.countByExample(selectExample);
                if (allCount == statueCount) {
                    //更新备料主表
                    WmsPreparationPlan updatePlan = new WmsPreparationPlan();
                    updatePlan.setPpStatus(String.valueOf(WmsPreparationPlanEnum.WMS_PLAN_FINISH.getValue()));
                    updatePlan.setGmtUpdate(new Date());
                    updatePlan.setPpId(detail.getVdPpId());
                    wmsPreparationPlanMapper.updateByPrimaryKeySelective(updatePlan);
                    //更新任务表中备料确认时间
                    //2018-1-18 bugfix状态校验:最后一个任务的完成时候 写入整个交接单下的任务备料确认时间
                    wmsOutboundTaskExtMapper.updateBatchBlConfirmTimeForJM(wmsOutboundTask);
                    //wmsOutboundTask.setOtBlConfirmTime(new Date());
                    //wmsOutboundTask.setGmtModify(new Date());
                }
            }
        }
    }

    /**
     * 更新备料状态
     *
     * @param vin             车架号
     * @param wmsOutboundTask 出库任务
     */
    private void updatePrepareStatus(String vin, WmsOutboundTask wmsOutboundTask) {
        if (StringUtils.isNotBlank(vin)) {
            WmsPreparationVehicleDetailExample detailExample = new WmsPreparationVehicleDetailExample();
            detailExample.setOrderByClause(" vd_id desc ");
            detailExample.createCriteria()
                    .andVdVinEqualTo(vin)
                    .andVdPpIdEqualTo(Long.valueOf(wmsOutboundTask.getOtBlId()))
                    .andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue());
            List<WmsPreparationVehicleDetail> detailList = vehicleDetailMapper.selectByExample(detailExample);
            if (CollectionUtils.isNotEmpty(detailList)) {
                WmsPreparationVehicleDetail detail = detailList.get(0);
                //在出库确认的扫描车架号更新备料明细表出库状态
                //detail.setVdOutstockStatus(String.valueOf(WmsOutboundStatusEnum.WMS_OUTBOUND_FINISH.getValue()));
                //vehicleDetailMapper.updateByPrimaryKeySelective(detail);
                if (detail.getVdPpId() != null) {
                    WmsPreparationPlan parentPlan = wmsPreparationPlanMapper.selectByPrimaryKey(detail.getVdPpId());
                    if (!String.valueOf(WmsPreparationPlanEnum.WMS_PLAN_CONFIRM.getValue()).equals(parentPlan.getPpStatus())) {
                        parentPlan.setPpStatus(String.valueOf(WmsPreparationPlanEnum.WMS_PLAN_CONFIRM.getValue()));
                        wmsPreparationPlanMapper.updateByPrimaryKey(parentPlan);
                    }
                }
            }
        }
    }

    /**
     * 更新库位分配为已删除
     */
    private void updateAllocation(String vin) {
        if (StringUtils.isNotBlank(vin)) {
            WmsInboundAllocationExample example = new WmsInboundAllocationExample();
            example.setOrderByClause(" al_id desc ");
            example.createCriteria()
                    .andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue())
                    .andAlVinEqualTo(vin);
            List<WmsInboundAllocation> allocationList = wmsInboundAllocationMapper.selectByExample(example);
            if (CollectionUtils.isNotEmpty(allocationList)) {
                WmsInboundAllocation wmsInboundAllocation = allocationList.get(0);
                wmsInboundAllocation.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
                wmsInboundAllocationMapper.updateByPrimaryKeySelective(wmsInboundAllocation);
            }
        }
    }

    /**
     * 获取交接单打印信息
     */
    @Override
    public HandoverDTO getPrintInfo(Long otId) throws Exception {
        logger.info("OutBoundTaskServiceImpl.getPrintInfo otId: {}", otId);
        //找到对应的备料任务
        WmsOutboundTask outboundTask = wmsOutboundTaskMapper.selectByPrimaryKey(otId);
        HandoverDTO handoverDTO = null;
        if (outboundTask != null) {
            //根据交接单号获取数据
            List<WmsShipmentPlan> shipmentPlanList = wmsShipmentPlanService.getShipmentPlanListByHandoverNo(outboundTask.getHoHandoverNumber());
            if (CollectionUtils.isEmpty(shipmentPlanList)) {
                throw new BusinessException("找不到对应的交接单数据");
            }

            //获取交接单数据
            handoverDTO = getHandoverDTO(shipmentPlanList);
            //获取条形码数据
            StringBuilder content = new StringBuilder();
            //content.append(handoverDTO.getWaybillNo())
            //        .append("-")
            //        .append(BarCodeTypeEnum.HANDOVER.getCode());
            content.append(handoverDTO.getWaybillNo());
            byte[] generate = BarCodeUtils.generate(content.toString());
            String encode64 = new Base64().encodeToString(generate);
            //BASE64Encoder base64 = new BASE64Encoder();
            //String encode64 = base64.encode(generate);
            handoverDTO.setImage(encode64);

            //装车道
            handoverDTO.setEstimateLane(outboundTask.getOtEstimateLane());

            List<WmsPreparationVehicleDetail> vehicleDetailList = wmsPreparationPlanService.getDetailListByHandoverNo(outboundTask.getHoHandoverNumber());
            List<HandoverDetailDTO> detailDTOList = null;
            if (CollectionUtils.isNotEmpty(vehicleDetailList)) {
                List<String> handoverNoList = new ArrayList<>();
                HandoverDetailDTO detailDTO = null;
                detailDTOList = new ArrayList<>();
                for (WmsPreparationVehicleDetail detail : vehicleDetailList) {
                    if (detail != null) {
                        detailDTO = new HandoverDetailDTO();
                        saveHandoverDetailInfo(detail, detailDTO, shipmentPlanList);
                        detailDTOList.add(detailDTO);
                        handoverNoList.add(detail.getHoHandoverNumber());
                    }
                }

                if (CollectionUtils.isNotEmpty(handoverNoList)) {
                    WmsShipmentPlanExample shipmentPlanExample = new WmsShipmentPlanExample();
                    WmsShipmentPlanExample.Criteria planExampleCriteria = shipmentPlanExample.createCriteria();
                    planExampleCriteria.andHoHandoverNumberIn(handoverNoList);
                    planExampleCriteria.andSpIsRemainEqualTo("否");
                    int countByExample = shipmentPlanMapper.countByExample(shipmentPlanExample);
                    if (handoverDTO != null) {
                        handoverDTO.setStandardNum(countByExample);
                    }
                }
            }
            if (handoverDTO != null && CollectionUtils.isNotEmpty(detailDTOList)) {
                handoverDTO.setAllNum(detailDTOList.size());
                handoverDTO.setDetailList(detailDTOList);
            }
        }

        return handoverDTO;
    }

    /**
     * 出库确认获取车架号列表 - 君马库
     */
    @Override
    public List<String> getVinList(BarCodeBO barCodeBO) throws Exception {
        logger.info("OutBoundTaskServiceImpl.getVinList barCodeBO: {}", barCodeBO);
        //交接单
        //交接单
        List<String> vinList = new ArrayList<>();
        //if (BarCodeTypeEnum.HANDOVER.getCode().equals(barCodeBO.getType()) && StringUtils.isNotBlank(barCodeBO.getOrderNo())) {
        if (OrderHeadEnum.HANDOVER.getCode().equals(barCodeBO.getType()) && StringUtils.isNotBlank(barCodeBO.getOrderNo())) {
            WmsOutboundTaskExample example = new WmsOutboundTaskExample();
            example.createCriteria().andHoHandoverNumberEqualTo(barCodeBO.getOrderNo());
            List<WmsOutboundTask> wmsOutboundTasks = wmsOutboundTaskMapper.selectByExample(example);
            if (CollectionUtils.isNotEmpty(wmsOutboundTasks)) {
                wmsOutboundTasks.stream()
                        .filter(task -> task != null && StringUtils.isNotBlank(task.getOtVin()))
                        .forEach(task -> vinList.add(task.getOtVin()));

                return vinList;
            }
        }
        //维修单
        //if (BarCodeTypeEnum.REPIR.getCode().equals(barCodeBO.getType()) && StringUtils.isNotBlank(barCodeBO.getOrderNo())) {
        if (OrderHeadEnum.REPIR.getCode().equals(barCodeBO.getType()) && StringUtils.isNotBlank(barCodeBO.getOrderNo())) {
            List<WmsInboundRepair> repairList = inboundRepairService.getRepairListByRepairNo(barCodeBO.getOrderNo());
            if (CollectionUtils.isNotEmpty(repairList)) {
                repairList.stream()
                        .filter(repair -> repair != null && StringUtils.isNotBlank(repair.getRpVin()))
                        .forEach(repair -> vinList.add(repair.getRpVin()));

                return vinList;
            }
        }
        //借车单
        //if (BarCodeTypeEnum.BORROW.getCode().equals(barCodeBO.getType()) && StringUtils.isNotBlank(barCodeBO.getOrderNo())) {
        if (OrderHeadEnum.BORROW.getCode().equals(barCodeBO.getType()) && StringUtils.isNotBlank(barCodeBO.getOrderNo())) {
            List<WmsBorrowCarDetail> carDetailList = borrowCarService.getBorrowCarDetaiListByBorrowNo(barCodeBO.getOrderNo());
            if (CollectionUtils.isNotEmpty(carDetailList)) {
                carDetailList.stream()
                        .filter(detail -> detail != null && StringUtils.isNotBlank(detail.getBdVin()))
                        .forEach(detail -> vinList.add(detail.getBdVin()));

                return vinList;
            }
        }
        return null;
    }

    /**
     * 出库确认web端 已调整 - 君马库
     */
    @Override
    public List<String> updateToOutConfirm(OutboundTaskConfirmFormBO taskConfirmFormBO, String whCode) throws Exception {
        logger.info("OutBoundTaskServiceImpl.updateToOutConfirm vin: {}", taskConfirmFormBO);
        //TODO - linbao
        //校验
        if (taskConfirmFormBO == null
                || CollectionUtils.isEmpty(taskConfirmFormBO.getVinList())
                || StringUtils.isBlank(taskConfirmFormBO.getVin())) {
            throw new BusinessException("参数为空");
        }

        if (taskConfirmFormBO.getVin().length() != 17) {
            throw new BusinessException("请输入长度为17位的车架号");
        }
        WmsInventoryLocation locationByVin = wmsInventoryService.getInventoryLocationByVin(taskConfirmFormBO.getVin());
        if (locationByVin == null) {
            throw new BusinessException("找不到对应的库存");
        }
        if (InventoryLocationStatusEnum.MAINTAIN_LOCK_50.getCode().equals(locationByVin.getStatus())) {
            throw new BusinessException("已出库, 不可重复出库");
        }

        //step-1 判断需要出库的车架号是否在已经从查询出来的数据中
        List<String> vinList = taskConfirmFormBO.getVinList();
        Iterator<String> iterator = vinList.iterator();
        String toOutVin = null;
        while (iterator.hasNext()) {
            String vin = iterator.next();
            if (vin != null && vin.equals(taskConfirmFormBO.getVin())) {
                toOutVin = vin;
                iterator.remove();
            }
        }

        //step-2 存在则允许出库
        if (StringUtils.isNotBlank(toOutVin)) {
            //需要出库的车架号
            deleteInventory(toOutVin);
        }

        //更新库位状态为已出库, 并且逻辑删除
        wmsInventoryService.updateStatusLocationByVin(toOutVin, InventoryLocationStatusEnum.MAINTAIN_LOCK_50.getCode());

        //step-3 根据类型查询不同的表
        WmsOutOfStorage storage = getStorage(taskConfirmFormBO, whCode);
        if (storage != null) {
            wmsOutOfStorageMapper.insertSelective(storage);
            //使用定时任务调用出入库的接口DCS SAP
        }

        //更新交接单状态
        updateHandoverStatus(toOutVin);

        //使用定时任务调用交接单DCS SAP
        //if (BarCodeTypeEnum.HANDOVER.getCode().equals(taskConfirmFormBO.getType())) {
        //    updateOunboundTask(taskConfirmFormBO.getVin());
        //    WmsHandoverOrderExample example = new WmsHandoverOrderExample();//过滤已经处理成功的数据
        //    example.createCriteria().andSernrEqualTo(taskConfirmFormBO.getVin()).andSendStatusNotEqualTo(SendStatusEnum.SEND_SUCCESS.getValue());
        //    List<WmsHandoverOrder> handoverOrderList = handoverOrderMapper.selectByExample(example);
        //    if (CollectionUtils.isNotEmpty(handoverOrderList)) {
        //        //调用交接单dcs接口
        //        try {
        //            wmsJmDcsService.saveDlvBillInfoImport(handoverOrderList);
        //        } catch (Exception e) {
        //            logger.error("OutBoundTaskServiceImpl.getPrintInfo otId: {}", e);
        //            throw new BusinessException("同步DCS接口异常!");
        //        }
        //    }
        //}
        return vinList;
    }

    /**
     * 更新交接单状态
     */
    private void updateHandoverStatus(String vin) {
        if (StringUtils.isNotBlank(vin)) {
            //获取数据
            WmsPreparationVehicleDetailExample detailExample = new WmsPreparationVehicleDetailExample();
            detailExample.createCriteria()
                    .andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue())
                    .andVdVinEqualTo(vin);
            List<WmsPreparationVehicleDetail> detailList = vehicleDetailMapper.selectByExample(detailExample);
            if (CollectionUtils.isNotEmpty(detailList)) {
                WmsPreparationVehicleDetail detail = detailList.get(0);
                if (detail != null && detail.getVdPpId() != null) {

                    WmsPreparationVehicleDetailExample selectExample = new WmsPreparationVehicleDetailExample();
                    WmsPreparationVehicleDetailExample.Criteria criteria = selectExample.createCriteria();
                    criteria.andVdPpIdEqualTo(detail.getVdPpId());
                    criteria.andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue());
                    int allCount = vehicleDetailMapper.countByExample(selectExample);

                    criteria.andVdOutstockStatusEqualTo(String.valueOf(WmsOutboundStatusEnum.WMS_OUTBOUND_FINISH.getValue()));
                    int statusCount = vehicleDetailMapper.countByExample(selectExample);
                    //所有的备料都已经完成
                    if (allCount == statusCount) {
                        WmsPreparationPlan preparationPlan = wmsPreparationPlanMapper.selectByPrimaryKey(detail.getVdPpId());
                        if (preparationPlan != null && StringUtils.isNotBlank(preparationPlan.getPpGroupBoardNo())) {
                            WmsHandoverOrderExample updateExample = new WmsHandoverOrderExample();
                            updateExample.createCriteria()
                                    .andGbnoEqualTo(preparationPlan.getPpGroupBoardNo())
                                    .andSendStatusEqualTo(SendStatusEnum.SEND_INIT.getValue());
                            WmsHandoverOrder updateOrder = new WmsHandoverOrder();
                            updateOrder.setPreparationStatus(String.valueOf(WmsPreparationPlanEnum.WMS_PLAN_FINISH.getValue()));
                            updateOrder.setGmtUpdate(new Date());
                            wmsHandoverOrderMapper.updateByExampleSelective(updateOrder, updateExample);
                        }
                    }
                }
            }
        }
    }

    @Override
    public void updateHandOverOrderDcs() throws Exception {
        //1.查询交接单表中未处理的数据(现在要一个组板单数据全部传输)
        String byGBNO = wmsHandoverOrderCustomMapper.selectDcsGroupByGBNO();
        logger.info("OutBoundTaskServiceImpl.updateHandOverOrderDcs 未发送组板单号:{}", byGBNO);
        if (StringUtils.isNotBlank(byGBNO)) {
            WmsHandoverOrderExample orderExample = new WmsHandoverOrderExample();
            orderExample.createCriteria()
                    .andGbnoEqualTo(byGBNO);
            List<WmsHandoverOrder> wmsHandoverOrders = wmsHandoverOrderMapper.selectByExample(orderExample);
            ArrayList<String> dcsS = Lists.newArrayList();
            if (CollectionUtils.isNotEmpty(wmsHandoverOrders)) {
                wmsHandoverOrders.forEach(v -> {
                    if (SendStatusEnum.SEND_INIT.getValue().equals(v.getSendStatus())) {
                        dcsS.add(v.getSendStatus());
                    }
                });
                //执行调用接口进行数据
                if (CollectionUtils.isNotEmpty(dcsS)) {
                    wmsJmDcsService.saveDlvBillInfoImport(wmsHandoverOrders);
                }
            }
        }
    }

    @Override
    public void updateHandOverOrderSap() throws Exception {
        //1.查询交接单表中未处理的数据(现在要一个组板单数据全部传输)
        String byGBNO = wmsHandoverOrderCustomMapper.selectSapGroupByGBNO();
        logger.info("OutBoundTaskServiceImpl.updateHandOverOrderSap 未发送组板单号:{}", byGBNO);
        if (StringUtils.isNotBlank(byGBNO)) {
            WmsHandoverOrderExample orderExample = new WmsHandoverOrderExample();
            orderExample.createCriteria()
                    .andGbnoEqualTo(byGBNO);
            List<WmsHandoverOrder> wmsHandoverOrders = wmsHandoverOrderMapper.selectByExample(orderExample);
            ArrayList<String> sapList = Lists.newArrayList();
            if (CollectionUtils.isNotEmpty(wmsHandoverOrders)) {
                wmsHandoverOrders.forEach(v -> {
                    if (SendStatusEnum.SEND_INIT.getValue().equals(v.getSendStatusSap())) {
                        sapList.add(v.getSendStatusSap());
                    }
                });
                //执行调用接口进行数据
                if (CollectionUtils.isNotEmpty(sapList)) {
                    wmsJmSapService.saveHandoverOrderToSap(wmsHandoverOrders);
                }
            }
        }
    }

    /**
     * <p>
     * 2018-4-27 君马dcs交接单发送整体组板数据,sap可以支持部分发送。
     * </p>
     */
    @Override
    public void updateHandOverOrderDcsExcp() throws Exception {
        //查询交接单异常表中为发送异常的数据及次数<=5的(最终状态为空的数据)--接口调整
        String byGBNO = wmsHandoverOrderCustomMapper.selectGroupByGBNODcsExcp();
        logger.info("OutBoundTaskServiceImpl.updateHandOverOrderDcsExcp 发送异常组板单号:{}", byGBNO);
        if (StringUtils.isNotBlank(byGBNO)) {
            //发送dcs
            WmsHandoverOrderExample orderExample = new WmsHandoverOrderExample();
            orderExample.createCriteria()
                    .andGbnoEqualTo(byGBNO);
            List<WmsHandoverOrder> dcsOrders = wmsHandoverOrderMapper.selectByExample(orderExample);
            if (CollectionUtils.isNotEmpty(dcsOrders)) {
                ArrayList<String> dcsS = Lists.newArrayList();
                dcsOrders.forEach(v -> {
                    if (!SendStatusEnum.SEND_SUCCESS.getValue().equals(v.getSendStatus())) {
                        dcsS.add(v.getSendStatus());
                    }
                });
                if (CollectionUtils.isNotEmpty(dcsS)) {
                    wmsJmDcsService.saveDlvBillInfoImport(dcsOrders);
                }
            }
        }
    }

    @Override
    public void updateHandOverOrderSapExcp() throws Exception {
        String byGBNO = wmsHandoverOrderCustomMapper.selectGroupByGBNOSapExcp();
        logger.info("OutBoundTaskServiceImpl.updateHandOverOrderDcsExcp 发送异常组板单号:{}", byGBNO);
        //发送sap
        WmsHandoverOrderExcpExample excpExample = new WmsHandoverOrderExcpExample();
        excpExample.createCriteria()
                .andSendStatusSapNotEqualTo(SendStatusEnum.SEND_SUCCESS.getValue())
                .andFinalSendStatusSapIsNull()
                .andGbnoEqualTo(byGBNO);
        List<WmsHandoverOrderExcp> sapExcps = wmsHandoverOrderExcpMapper.selectByExample(excpExample);
        if (CollectionUtils.isNotEmpty(sapExcps)) {
            //执行调用接口--同步sap数据
            List<WmsHandoverOrder> wmsHandoverOrders = Lists.newArrayList();
            sapExcps.forEach(v -> {
                WmsHandoverOrder wmsHandoverOrder = new WmsHandoverOrder();
                BeanUtils.copyProperties(v, wmsHandoverOrder);
                wmsHandoverOrders.add(wmsHandoverOrder);
            });
            wmsJmSapService.saveHandoverOrderToSap(wmsHandoverOrders);
        }
    }

    /**
     * <p>
     * 2018-3-1 新需求:君马仓库需要增加发送发运数据到对方crm系统
     * 说明:发送交接单数据给crm系统
     * </p>
     *
     * @throws Exception 异常
     */
    @Override
    public void updateHandOverOrderToCRM() throws Exception {
        if (logger.isInfoEnabled()) {
            logger.info("OutBoundTaskServiceImpl.updateHandOverOrderToCRM start:");
        }
        //先查询发送crm的对应的异常数据是否发送完成
        HashMap<String, Object> params = Maps.newHashMap();
        params.put("excp_status", SendStatusEnum.SEND_FAILED.getValue());
        params.put("not_send", SendStatusEnum.SEND_INIT.getValue());
        List<WmsHandoverOrderExcp> excps = wmsHandoverOrderCustomMapper.selectExcpHandoverOrderForCRM(params);
        if (CollectionUtils.isNotEmpty(excps)) {
            //就发送异常的数据到crm系统
            WmsHandoverOrderExcp wmsHandoverOrderExcp = excps.get(0);
            List<WmsHandoverOrder> orders = new ArrayList<>();
            WmsHandoverOrder wmsHandoverOrder = new WmsHandoverOrder();
            BeanUtils.copyProperties(wmsHandoverOrderExcp, wmsHandoverOrder);
            orders.add(wmsHandoverOrder);
            wmsJmCRMService.saveHandoverOrderToCRM(orders);
        } else {
            //找正常的数据发送到crm系统
            List<WmsHandoverOrder> orders = wmsHandoverOrderCustomMapper.selectHandoverOrderForCRM(params);
            if (CollectionUtils.isNotEmpty(orders)) {
                wmsJmCRMService.saveHandoverOrderToCRM(orders);
            }
        }

    }

    /**
     * 君马APP 出库确认获得对应的单据号下的未出库车架号
     * 扫描纸质单号:维修单、出库交接单、出库维修单、借车单
     */
    @Override
    public WmsOutboundResultDTO getOrderMsg(OutboundConfirmBO bo) {
        logger.info("OutBoundTaskServiceImpl.getOrderMsg barCodeBO: {}", bo);
        if (Objects.equals(bo, null)) {
            throw new BusinessException("传入参数为空!");
        }
        String orderNo = bo.getOrderNo();
        if (StringUtils.isBlank(orderNo)) {
            throw new BusinessException("扫描的订单号为空!");
        }
        if (StringUtils.isBlank(bo.getWhCode())) {
            throw new BusinessException("传入仓库code为空!");
        }
        if (StringUtils.isBlank(bo.getUserId())) {
            throw new BusinessException("传入的用户id为空");
        }
        if ((!Objects.equals(bo.getWhCode(), WhCodeEnum.JM_CS.getValue())) &&
                (!Objects.equals(bo.getWhCode(), WhCodeEnum.JM_XY.getValue()))) {
            throw new BusinessException("仓库不支持该类型操作");
        }
        //1.查询单号信息
        if (orderNo.length() <= 2) {
            throw new BusinessException("订单号长度不正确!");
        }
        String typeHead = orderNo.substring(0, 2);
        WmsOutboundResultDTO resultDTO = new WmsOutboundResultDTO();

        //查询所有的备料完成的车架号判断是否有出库确认  有就是已出库
        ArrayList<WmsOutboundTask> has_out = Lists.newArrayList();
        ArrayList<WmsOutboundTask> not_out = Lists.newArrayList();

        if (OrderHeadEnum.HANDOVER.getCode().equals(typeHead)) {
            //交接单
            //单号根据头判断是什么类型,根据库存库位的状态判断是否已出库 判断是否已经备料完成
            //WmsOutboundTaskExample taskExample = new WmsOutboundTaskExample();
            //taskExample.createCriteria().andHoHandoverNumberEqualTo(bo.getOrderNo())
            //        .andOtIsChangeEqualTo(TaskIsNeedChangeEnum.NO_CHANGE.getCode())
            //        .andIsDeletedEqualTo(DeleteFlagEnum.HAS_QUIT.getValue())
            //        .andOtStatusEqualTo(String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue()));
            List<WmsOutboundTask> has_outbound = wmsOutboundTaskExtMapper.selectHasPrepareFinishedList(bo.getOrderNo(), String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue()));

            List<WmsOutboundTask> not_outbound = wmsOutboundTaskExtMapper.selectNotPrepareFinishedList(bo.getOrderNo()
                    , String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_CANCLE.getValue())
                    , String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue()));
            if (not_outbound.size() > 0) {
                throw new BusinessException("该单号存在未完成任务的车辆不能进行该操作");
            }
            if (has_outbound.size() <= 0) {
                throw new BusinessException("未查询到该单号的信息!");
            }
            //全部任务完成
            updateReturnList(has_out, not_out, has_outbound);
            resultDTO.setOutboundType(WmsOutBoundTypeEnum.ZTYPE_Z1.getValue());
        }
        if (OrderHeadEnum.REPIR.getCode().equals(typeHead)) {
            //维修单
            WmsInboundRepairExample repairExample = new WmsInboundRepairExample();
            repairExample.createCriteria().andRpRepairNoEqualTo(bo.getOrderNo())
                    .andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue());
            List<WmsInboundRepair> wmsInboundRepairs = wmsInboundRepairMapper.selectByExample(repairExample);
            if (CollectionUtils.isEmpty(wmsInboundRepairs))
                throw new BusinessException("未查询到对应单号:" + bo.getOrderNo() + "的信息");
            WmsInboundRepair repair = wmsInboundRepairs.get(0);
            if (WmsInboundRepairStatusEnum.NOT_DEAL.getCode().equals(repair.getRpStatus()))
                throw new BusinessException("该维修单未提交维修,不能进行此操作");
            if (WmsInboundRepairStatusEnum.DEALED.getCode().equals(repair.getRpStatus()))
                throw new BusinessException("该维修单已处理完成");
            //判断出库状态
            if (RepairInOutStatusEnum.NO_SEND.getCode().equals(repair.getRpInOutStatus())) {
                WmsOutboundTask outboundTask = wmsOutboundTaskMapper.selectByPrimaryKey(Long.valueOf(repair.getRpOdId()));
                not_out.add(outboundTask);
            }
            if (RepairInOutStatusEnum.HAVE_SEND.getCode().equals(repair.getRpInOutStatus())) {
                WmsOutboundTask outboundTask = wmsOutboundTaskMapper.selectByPrimaryKey(Long.valueOf(repair.getRpOdId()));
                has_out.add(outboundTask);
            }
            resultDTO.setOutboundType(WmsOutBoundTypeEnum.ZTYPE_Z2.getValue());
        }
        if (OrderHeadEnum.BORROW.getCode().equals(typeHead)) {
            //借车
            //单号根据头判断是什么类型,根据库存库位的状态判断是否已出库 判断是否已经备料完成
            List<WmsOutboundTask> has_outbound = wmsOutboundTaskExtMapper.selectHasPrepareFinishedList(bo.getOrderNo(), String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue()));

            List<WmsOutboundTask> not_outbound = wmsOutboundTaskExtMapper.selectNotPrepareFinishedList(bo.getOrderNo()
                    , String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_CANCLE.getValue())
                    , String.valueOf(WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue()));
            if (not_outbound.size() > 0) {
                throw new BusinessException("该单号存在未完成任务的车辆不能进行该操作");
            }
            if (has_outbound.size() <= 0) {
                throw new BusinessException("未查询到该单号的信息!");
            }
            //全部任务完成
            updateReturnList(has_out, not_out, has_outbound);
            resultDTO.setOutboundType(WmsOutBoundTypeEnum.ZTYPE_Z3.getValue());
        }
        //这里面的状态只是备料的状态；
        resultDTO.setOrderNo(orderNo);
        resultDTO.setHasOutbound(has_out);
        resultDTO.setNotOutbound(not_out);
        resultDTO.setNotOutboundNum(not_out.size() <= 0 ? 0 : not_out.size());
        resultDTO.setHasOutboundNum(has_out.size() <= 0 ? 0 : has_out.size());
        return resultDTO;
    }

    /**
     * 更新实际出库的数量
     */
    private void updateReturnList(ArrayList<WmsOutboundTask> has_out, ArrayList<WmsOutboundTask> not_out, List<WmsOutboundTask> has_outbound) {
        if (CollectionUtils.isNotEmpty(has_outbound)) {
            for (WmsOutboundTask next : has_outbound) {
                String otVin = next.getOtVin();
                //查询库存库位表
                WmsInventoryLocationExample locationExample = new WmsInventoryLocationExample();
                //已出库的数据已经逻辑删除掉了
                locationExample.createCriteria().andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue())
                        .andInvlocVinEqualTo(otVin)
                        .andStatusNotEqualTo(InventoryLocationStatusEnum.MAINTAIN_LOCK_50.getCode());
                List<WmsInventoryLocation> wmsInventoryLocations = wmsInventoryLocationMapper.selectByExample(locationExample);
                if (CollectionUtils.isEmpty(wmsInventoryLocations)) {
                    has_out.add(next);//未出库列表添加
                } else {
                    not_out.add(next);
                }
            }
        }
    }

    /**
     * 扫描车架号进行出库确认并更新状态
     *
     * @param bo 参数封装
     * @throws Exception 异常
     */
    @Override
    public void updateOutboundByVin(OutboundConfirmBO bo) throws Exception {
        logger.info("OutBoundTaskServiceImpl.updateOutboundByVin barCodeBO: {}", bo);
        if (Objects.equals(bo, null)) {
            throw new BusinessException("传入参数为空!");
        }
        if (StringUtils.isBlank(bo.getVin()))
            throw new BusinessException("传入的车架号为空!");
        String orderNo = bo.getOrderNo();
        if (StringUtils.isBlank(orderNo)) {
            throw new BusinessException("扫描的订单号为空!");
        }
        //如果是借车 或者 维修出库 还需要更新对应的单号的状态
        if (orderNo.length() <= 2) {
            throw new BusinessException("该车辆的单号不正确!");
        }
        if (StringUtils.isBlank(bo.getWhCode())) {
            throw new BusinessException("传入仓库code为空!");
        }
        if (StringUtils.isBlank(bo.getUserId())) {
            throw new BusinessException("传入的用户id为空");
        }
        if ((!Objects.equals(bo.getWhCode(), WhCodeEnum.JM_CS.getValue())) &&
                (!Objects.equals(bo.getWhCode(), WhCodeEnum.JM_XY.getValue()))) {
            throw new BusinessException("仓库不支持该类型操作");
        }
        //1.校验车架号是否是已完成备料及是否已经出库
        List notOutbound = getOrderMsg(bo).getNotOutbound();
        Iterator iterator = notOutbound.iterator();
        WmsOutboundTask notBoundTask = null;
        while (iterator.hasNext()) {
            WmsOutboundTask next = (WmsOutboundTask) iterator.next();
            if (StringUtils.isNotBlank(next.getOtVin()) && next.getOtVin().equals(bo.getVin())) {
                //找到未出库的车架号
                notBoundTask = next;
                break;
                //iterator.remove();
            }
        }
        if (Objects.equals(notBoundTask, null)) {
            throw new BusinessException("要出库的车架号不在该单存在");
        }
        //校验验车状态
        if (WmsOutboundInspectStatusEnum.WAYBILL_INIT.getValue() == (notBoundTask.getInspectStatus())) {
            throw new BusinessException("该车辆未进行验车操作,请先验车");
        }
        //查用户
        SysUser sysUser = sysUserMapper.selectByPrimaryKey(Integer.valueOf(bo.getUserId()));
        //维修单出库的业务
        if (OrderHeadEnum.REPIR.getCode().equals(bo.getOrderNo().substring(0, 2))) {
            //维修单 更新状态
            WmsInboundRepairExample repairExample = new WmsInboundRepairExample();
            repairExample.createCriteria().andRpRepairNoEqualTo(bo.getOrderNo())
                    .andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue());
            List<WmsInboundRepair> wmsInboundRepairs = wmsInboundRepairMapper.selectByExample(repairExample);

            if (CollectionUtils.isEmpty(wmsInboundRepairs))
                throw new BusinessException("未查询到对应单号:" + bo.getOrderNo() + "的信息");
            WmsInboundRepair repair = wmsInboundRepairs.get(0);
            if (WmsInboundRepairStatusEnum.NOT_DEAL.getCode().equals(repair.getRpStatus()))
                throw new BusinessException("该维修单未提交维修,不能进行此操作");
            if (WmsInboundRepairStatusEnum.DEALED.getCode().equals(repair.getRpStatus()))
                throw new BusinessException("该维修单已处理完成");
            //判断出库状态(因为涉及重复维修出库的情况,使用其真实释放库存的标识ottype确认该维修单是否出库)
            if (OutBoundTaskTypeEnum.REPAIR_OUT.getCode().equals(notBoundTask.getOtType()))
                throw new BusinessException("该维修单车架号+" + bo.getVin() + "已经维修出库,无需重复操作");
            //if (RepairInOutStatusEnum.HAVE_SEND.getCode().equals(repair.getRpInOutStatus())) {
            //    throw new BusinessException("该维修单车架号+" + bo.getVin() + "已经维修出库,无需重复操作");
            //}
            //看维修的状态  如果验车地方选择的是入库区再验车--释放库存，写入接口表
            String outboundValue = String.valueOf(WmsRepairInAndOutTypeEnum.OUTBOUND_REPAIR.getValue());
            String inboundPlace = String.valueOf(WmsRepairInspectPlaceEnum.INBOUND_PLACE.getValue());
            repair.setRpInOutStatus(RepairInOutStatusEnum.HAVE_SEND.getCode());
            repair.setGmtUpdate(new Date());
            repair.setModifyUserId(bo.getUserId());
            if (sysUser != null) {
                repair.setModifyUserName(sysUser.getName());
            }
            wmsInboundRepairMapper.updateByPrimaryKeySelective(repair);
            //看维修的状态  如果验车地方选择的是入库区再验车--释放库存，写入接口表
            if (outboundValue.equals(repair.getRpInandoutType())
                    && inboundPlace.equals(repair.getRepairInspectPlace())) {
                //真的释放库存时侯,修改任务单状态为维修出库
                notBoundTask.setOtType(OutBoundTaskTypeEnum.REPAIR_OUT.getCode());
                notBoundTask.setGmtModify(new Date());
                notBoundTask.setModifyUserId(bo.getUserId());
                if (sysUser != null) {
                    notBoundTask.setModifyUserName(sysUser.getName());
                }
                wmsOutboundTaskMapper.updateByPrimaryKeySelective(notBoundTask);
                //释放库存
                WmsInventoryLocationExample locationExample = new WmsInventoryLocationExample();
                locationExample.createCriteria().andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue())
                        .andInvlocVinEqualTo(repair.getRpVin())
                        .andStatusNotEqualTo(InventoryLocationStatusEnum.MAINTAIN_LOCK_50.getValue());
                List<WmsInventoryLocation> wmsInventoryLocations = wmsInventoryLocationMapper.selectByExample(locationExample);
                if (CollectionUtils.isNotEmpty(wmsInventoryLocations)) {
                    //2.更新出库任务表中出库状态
                    WmsInventoryLocation inventoryLocation = wmsInventoryLocations.get(0);
                    inventoryLocation.setGmtUpdate(new Date());
                    inventoryLocation.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
                    //更新状态为已出库
                    inventoryLocation.setModifyUserId(bo.getUserId());
                    if (sysUser != null) {
                        inventoryLocation.setModifyUserName(sysUser.getName());
                    }
                    inventoryLocation.setStatus(InventoryLocationStatusEnum.MAINTAIN_LOCK_50.getCode());
                    //逻辑删除库存表数据
                    wmsInventoryLocationMapper.updateByPrimaryKeySelective(inventoryLocation);

                    updateInventory(bo, sysUser, inventoryLocation);

                    //3.更新备料计划明细表中状态
                    WmsPreparationVehicleDetailExample detailExample = new WmsPreparationVehicleDetailExample();
                    detailExample.createCriteria().andVdVinEqualTo(repair.getRpVin())
                            .andIsDeletedNotEqualTo(DeleteFlagEnum.NORMAL.getValue());
                    List<WmsPreparationVehicleDetail> wmsPreparationVehicleDetails = wmsPreparationVehicleDetailMapper.selectByExample(detailExample);
                    updatePreparationDetails(sysUser, wmsPreparationVehicleDetails);

                    //维修出库写入接口表
                    WmsOutOfStorage wmsOutOfStorage = new WmsOutOfStorage();
                    wmsOutOfStorage.setMatnr(repair.getRpMaterialCode());//物料编码
                    wmsOutOfStorage.setZtype(InboundOrderBusinessTypeEnum.Z3.getCode());//业务类型
                    wmsOutOfStorage.setSerialNo(bo.getOrderNo());//设置流水号
                    wmsOutOfStorage.setSernr(repair.getRpVin());//车架号
                    wmsOutOfStorage.setBldat(new Date());//出入库日期
                    wmsOutOfStorage.setZaction(WmsOutOfStorageAction.ACTION_OUTBOUND.getValue());//动作
                    //库存地点 - CS01-长沙 XY01-襄阳',
                    if (WarehouseEnum.JM_XY.getWhCode().equals(bo.getWhCode())) {
                        wmsOutOfStorage.setUmlgo("XY01");
                    }
                    if (WarehouseEnum.JM_CS.getWhCode().equals(bo.getWhCode())) {
                        wmsOutOfStorage.setUmlgo("CS01");
                    }
                    wmsOutOfStorage.setSendStatus(SendStatusEnum.SEND_INIT.getValue());
                    wmsOutOfStorage.setSendStatusSap(SendStatusEnum.SEND_INIT.getValue());
                    wmsOutOfStorageMapper.insertSelective(wmsOutOfStorage);
                }

            }
        }
        //正常交接单业务
        if (OrderHeadEnum.HANDOVER.getCode().equals(bo.getOrderNo().substring(0, 2))) {
            //正常的交接单业务 根据车架号查询库存库位表的状态
            WmsInventoryLocationExample locationExample = new WmsInventoryLocationExample();
            locationExample.createCriteria().andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue())
                    .andInvlocVinEqualTo(notBoundTask.getOtVin())
                    .andStatusNotEqualTo(InventoryLocationStatusEnum.MAINTAIN_LOCK_50.getValue());
            List<WmsInventoryLocation> wmsInventoryLocations = wmsInventoryLocationMapper.selectByExample(locationExample);
            if (CollectionUtils.isEmpty(wmsInventoryLocations)) {
                throw new BusinessException("该车架号已经出库,无需重复操作!");
            }
            //2.更新出库任务表中出库状态
            WmsInventoryLocation inventoryLocation = wmsInventoryLocations.get(0);
            inventoryLocation.setGmtUpdate(new Date());
            inventoryLocation.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
            //更新状态为已出库
            inventoryLocation.setModifyUserId(bo.getUserId());
            if (sysUser != null) {
                inventoryLocation.setModifyUserName(sysUser.getName());
            }
            inventoryLocation.setStatus(InventoryLocationStatusEnum.MAINTAIN_LOCK_50.getCode());
            //逻辑删除库存表数据
            wmsInventoryLocationMapper.updateByPrimaryKeySelective(inventoryLocation);
            //4.更新库存表中的状态
            updateInventory(bo, sysUser, inventoryLocation);
            //3.更新备料计划明细表中状态
            WmsPreparationVehicleDetailExample detailExample = new WmsPreparationVehicleDetailExample();
            detailExample.createCriteria().andVdVinEqualTo(bo.getVin())
                    .andIsDeletedNotEqualTo(DeleteFlagEnum.NORMAL.getValue());
            List<WmsPreparationVehicleDetail> wmsPreparationVehicleDetails = wmsPreparationVehicleDetailMapper.selectByExample(detailExample);
            updatePreparationDetails(sysUser, wmsPreparationVehicleDetails);
            //更新交接单状态
            updateHandoverStatus(notBoundTask.getOtVin());
        }

        //5.生成出库信息到出入库接口表中--只有借车出库，维修出库，才会写数据到接口表中；
        if (OrderHeadEnum.BORROW.getCode().equals(bo.getOrderNo().substring(0, 2))) {
            //更新库存
            WmsInventoryLocationExample locationExample = new WmsInventoryLocationExample();
            locationExample.createCriteria().andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue())
                    .andInvlocVinEqualTo(notBoundTask.getOtVin())
                    .andStatusNotEqualTo(InventoryLocationStatusEnum.MAINTAIN_LOCK_50.getValue());
            List<WmsInventoryLocation> wmsInventoryLocations = wmsInventoryLocationMapper.selectByExample(locationExample);
            if (CollectionUtils.isEmpty(wmsInventoryLocations)) {
                throw new BusinessException("该车架号已经出库,无需重复操作!");
            }
            //2.更新出库任务表中出库状态
            WmsInventoryLocation inventoryLocation = wmsInventoryLocations.get(0);
            inventoryLocation.setGmtUpdate(new Date());
            inventoryLocation.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
            //更新状态为已出库
            inventoryLocation.setModifyUserId(bo.getUserId());
            if (sysUser != null) {
                inventoryLocation.setModifyUserName(sysUser.getName());
            }
            inventoryLocation.setStatus(InventoryLocationStatusEnum.MAINTAIN_LOCK_50.getCode());
            //逻辑删除库存表数据
            wmsInventoryLocationMapper.updateByPrimaryKeySelective(inventoryLocation);
            //4.更新库存表中的状态
            updateInventory(bo, sysUser, inventoryLocation);
            //借车单  无更新内容
            WmsBorrowCarDetailExample carDetailExample = new WmsBorrowCarDetailExample();
            carDetailExample.createCriteria().andBdVinEqualTo(notBoundTask.getOtVin());
            List<WmsBorrowCarDetail> wmsBorrowCarDetails = wmsBorrowCarDetailMapper.selectByExample(carDetailExample);

            //借车出库写入接口表
            WmsOutOfStorage wmsOutOfStorage = new WmsOutOfStorage();
            if (CollectionUtils.isNotEmpty(wmsBorrowCarDetails)) {
                WmsBorrowCarDetail wmsBorrowCarDetail = wmsBorrowCarDetails.get(0);
                wmsOutOfStorage.setMatnr(wmsBorrowCarDetail.getBdMaterialCode());//物料编码
                wmsOutOfStorage.setZtype(InboundOrderBusinessTypeEnum.Z7.getCode());//业务类型
            }
            wmsOutOfStorage.setSerialNo(bo.getOrderNo());//设置流水号
            wmsOutOfStorage.setSernr(notBoundTask.getOtVin());//车架号
            wmsOutOfStorage.setBldat(new Date());//出入库日期
            wmsOutOfStorage.setZaction(WmsOutOfStorageAction.ACTION_OUTBOUND.getValue());//动作
            //库存地点 - CS01-长沙 XY01-襄阳',
            if (WarehouseEnum.JM_XY.getWhCode().equals(bo.getWhCode())) {
                wmsOutOfStorage.setUmlgo("XY01");
            }
            if (WarehouseEnum.JM_CS.getWhCode().equals(bo.getWhCode())) {
                wmsOutOfStorage.setUmlgo("CS01");
            }
            wmsOutOfStorage.setSendStatus(SendStatusEnum.SEND_INIT.getValue());
            wmsOutOfStorage.setSendStatusSap(SendStatusEnum.SEND_INIT.getValue());
            wmsOutOfStorageMapper.insertSelective(wmsOutOfStorage);
        }
        //调用接口出场闸门开启
        new Thread(() -> {
            try {
                gateControllerService.updateJmGateOut(sysUser, bo);
            } catch (BusinessException be) {
                logger.error("OutBoundTaskServiceImpl.gateControllerService.updateJmGateOut businessException:", be);
            } catch (Exception e) {
                logger.error("OutBoundTaskServiceImpl.gateControllerService.updateJmGateOut error:", e);
            }
        }).start();
    }

    /**
     * 出库记录导出--君马和重庆
     * <p>
     * 2018-1-22 出库记录查询页面增加“物料代码”、“配置”、“颜色代码”、“颜色”字段显示(君马)，导出的文件中也需要包含这四个字段
     * </p>
     *
     * @param dto      参数封装
     * @param request  请求
     * @param response 响应
     * @throws Exception 异常
     */
    @Override
    public void updateOutboundImportExcel(WmsOutboundImportExcelDTO dto,
                                          HttpServletRequest request,
                                          HttpServletResponse response) throws Exception {
        logger.info("OutBoundTaskServiceImpl.updateOutboundImportExcel param:{}", dto);
        if (Objects.equals(dto, null))
            throw new BusinessException("传入参数为空!");
        if (StringUtils.isBlank(dto.getWhCode()))
            throw new BusinessException("仓库code不能为空!");
        if (StringUtils.isBlank(dto.getUserId()))
            throw new BusinessException("用户Id不能为空!");
        if (StringUtils.isBlank(dto.getOutConfirmEndTime())
                && StringUtils.isBlank(dto.getOutConfirmStartTime())) {
            throw new BusinessException("请选择出库起止时间");
        }
        HashMap<String, Object> paramMap = Maps.newHashMap();
        //用户填写了出库确认时间
        if (StringUtils.isNotBlank(dto.getOutConfirmStartTime())) {
            paramMap.put("startBlConfirmTime", dto.getOutConfirmStartTime() + " 00:00:00");
        }
        if (StringUtils.isNotBlank(dto.getOutConfirmEndTime())) {
            paramMap.put("endBlConfirmTime", dto.getOutConfirmEndTime() + " 23:59:59");
        }
        if (StringUtils.isNotBlank(dto.getSpCarrier())) {
            paramMap.put("spCarrier", dto.getSpCarrier());
        }
        if (StringUtils.isNotBlank(dto.getSpCarrier())) {
            paramMap.put("spCarrier", dto.getSpCarrier());
        }
        paramMap.put("otWhCode", dto.getWhCode());
        paramMap.put("otQuitFlag", TaskQuitFlagEnum.NOT_QUIT.getValue());//非退库标识
        paramMap.put("otStatus", WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue());
        paramMap.put("notDel", DeleteFlagEnum.NORMAL.getValue());//过滤已删除
        paramMap.put("orderByClause", "a.ot_id desc");

        Workbook workbook = null;
        if (WhCodeEnum.UNLCN_XN_CQ.getValue().equals(dto.getWhCode())) {
            //List<WmsOutboundTaskDTO> dtoList = outboundTaskExtMapper.listOutboundRecordsForPage(paramMap);
            paramMap.put("spNotDel", WmsShipmentPlanModifyTypeEnum.DELETE.getValue());
            List<WmsOutboundTaskDTOForQuery> queryList = outboundTaskExtMapper.selectOutboundRecordsByParamForCQ(paramMap);
            if (CollectionUtils.isEmpty(queryList)) {
                throw new BusinessException("未查询到对应的数据");
            }
            //设置出库列表货主
            queryList.stream()
                    .filter(query -> query != null && StringUtils.isNotBlank(query.getOtVin()))
                    .forEach((WmsOutboundTaskDTOForQuery query) -> {
                        query.setOtCustomerName(WmsCustomerEnum.CQ_JL.getName());
                    });

            String[] headers = new String[]{
                    "车架号(VIN码)", "车型", "货主", "出库类型", "出库确认时间", "出库确认人",
                    "发运状态", "发运时间", "板车出库时间", "承运物流商"
            };
            //设置值
            workbook = updateExportToExcelForCQ("出库记录数据导出", headers, queryList, "yyyy-MM-dd HH:mm:ss");
        }
        //君马库
        if (WhCodeEnum.JM_CS.getValue().equals(dto.getWhCode())
                || WhCodeEnum.JM_XY.getValue().equals(dto.getWhCode())) {
            //List<WmsOutboundTaskDTOForQuery> queries = outboundTaskExtMapper.listOutboundRecordsForPageJm(paramMap);
            paramMap.put("notChange", TaskIsNeedChangeEnum.NO_CHANGE.getCode());
            paramMap.put("cantChange", TaskIsNeedChangeEnum.NOT_CAR_TO_CHANGE.getCode());
            outboundTaskExtMapper.updateSQLmode();
            List<WmsOutboundTaskDTOForQuery> queries = outboundTaskExtMapper.listOutboundRecordsForPageJmWithNotice(paramMap);
            //设置货主和其他字段补齐
            ArrayList<WmsOutboundTaskDTOForQuery> list = updateCustomerAndOtherFieldsForJM(queries);
            if (CollectionUtils.isEmpty(list)) {
                throw new BusinessException("未查询到对应的数据");
            }
            String[] headers = new String[]{
                    "车架号(VIN码)", "车型", "物料代码", "配置", "颜色代码", "颜色", "货主",
                    "出库类型", "出库确认时间", "出库确认人", "承运物流商", "经销商"
            };
            //设置值
            workbook = updateExportToExcelForJM("出库记录数据导出", headers, list, "yyyy-MM-dd HH:mm:ss");
        }
        if (workbook != null) {
            //输出流--提供下载
            try {
                response.setCharacterEncoding("utf-8");
                response.setContentType("application/vnd.ms-excel;charset=UTF-8");
                response.setHeader("Content-disposition", BrowerEncodeingUtils.getContentDisposition("OutboundRecordImportExcel.xls", request));
                ServletOutputStream outputStream = response.getOutputStream();
                workbook.write(outputStream);
            } catch (IOException e) {
                logger.error("OutBoundTaskServiceImpl.updateOutboundImportExcel IO_error:", e);
                throw new BusinessException("下载文件异常!");
            } finally {
                workbook.close();
            }
        }

    }

    /**
     * 出库记录导出--君马和重庆
     * <p>
     * 2018-1-22 出库记录查询页面增加“物料代码”、“配置”、“颜色代码”、“颜色”字段显示(君马)，导出的文件中也需要包含这四个字段
     * </p>
     *
     * @param dto      参数封装
     * @param request  请求
     * @param response 响应
     * @throws Exception 异常
     */
    @Deprecated
    @Override
    public void updateOutboundImportExcelOld(WmsOutboundImportExcelDTO dto,
                                             HttpServletRequest request,
                                             HttpServletResponse response) throws Exception {
        logger.info("OutBoundTaskServiceImpl.updateOutboundImportExcel param:{}", dto);
        Map<String, Object> paramMap = getParamAndCheck(dto);
        paramMap.put("isDeleted", DeleteFlagEnum.NORMAL.getValue());//过滤已删除
        if (WhCodeEnum.JM_XY.getValue().equals(dto.getWhCode()) || WhCodeEnum.JM_CS.getValue().equals(dto.getWhCode())) {
            paramMap.put("locationStatus", InventoryLocationStatusEnum.MAINTAIN_LOCK_50.getCode());
        }
        List<WmsOutboundTaskDTO> wmsOutboundTaskDTOList = outboundTaskExtMapper.listOutboundRecordForImport(paramMap);
        if (CollectionUtils.isEmpty(wmsOutboundTaskDTOList)) {
            throw new BusinessException("未查询到符合条件的数据");
        }

        String[] headers = null;
        HSSFWorkbook workbook = null;
        if (WhCodeEnum.JM_XY.getValue().equals(dto.getWhCode()) || WhCodeEnum.JM_CS.getValue().equals(dto.getWhCode())) {
            ArrayList<WmsOutboundTaskDTOForQuery> list = updateCustomerAndOtherFieldsForJMImport(wmsOutboundTaskDTOList);
            headers = new String[]{
                    "车架号(VIN码)", "车型", "物料代码", "配置", "颜色代码", "颜色", "货主", "出库类型", "出库确认时间", "出库确认人"};
            //设置值
            workbook = updateExportToExcelForJM("出库记录数据导出", headers, list, "yyyy-MM-dd HH:mm:ss");
        }
        if (WhCodeEnum.UNLCN_XN_CQ.getValue().equals(dto.getWhCode())) {
            ArrayList<WmsOutboundTaskDTOForQuery> list = updateCustomerNameAndOtherFieldsForCQ(wmsOutboundTaskDTOList);
            headers = new String[]{
                    "车架号(VIN码)", "车型", "货主", "出库类型", "出库确认时间", "出库确认人",
                    "发运状态", "发运时间", "板车出库时间"};
            //设置值
            workbook = updateExportToExcelForCQ("出库记录数据导出", headers, list, "yyyy-MM-dd HH:mm:ss");
        }
        if (workbook != null) {
            //输出流--提供下载
            BufferedOutputStream bufferedOutputStream = null;
            BufferedInputStream bufferedInputStream = null;
            ByteArrayOutputStream bos = null;
            ByteArrayInputStream inputStream = null;
            ServletOutputStream outputStream = null;
            try {
                bos = new ByteArrayOutputStream(1024);
                workbook.write(bos);
                response.setCharacterEncoding("utf-8");
                response.setContentType("application/vnd.ms-excel;charset=UTF-8");
                response.setHeader("Content-disposition", BrowerEncodeingUtils.getContentDisposition("OutboundRecordImportExcel.xls", request));
                inputStream = new ByteArrayInputStream(bos.toByteArray());
                outputStream = response.getOutputStream();
                bufferedOutputStream = new BufferedOutputStream(outputStream);
                bufferedInputStream = new BufferedInputStream(inputStream);
                byte[] bytes = new byte[1024];
                int len;
                while ((len = inputStream.read(bytes)) != -1) {
                    outputStream.write(bytes, 0, len);
                }
            } catch (IOException e) {
                logger.error("OutBoundTaskServiceImpl.updateOutboundImportExcel IO_error:", e);
                throw new BusinessException("下载文件异常!");
            } finally {
                if (bufferedInputStream != null) {
                    bufferedInputStream.close();
                }
                if (bufferedOutputStream != null) {
                    bufferedOutputStream.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
                if (bos != null) {
                    bos.close();
                }
                if (workbook != null) {
                    workbook.close();
                }
            }
        }

    }

    /**
     * @param title             标题
     * @param headers           表头
     * @param taskDTOForQueries 参数列表
     * @param pattern           @Title exportExcel
     */
    private HSSFWorkbook updateExportToExcelForJM(String title,
                                                  String[] headers,
                                                  ArrayList<WmsOutboundTaskDTOForQuery> taskDTOForQueries,
                                                  String pattern) {
        // 声明一个工作薄
        HSSFWorkbook workbook = new HSSFWorkbook();
        // 生成一个表格
        HSSFSheet sheet = workbook.createSheet(title);
        // 设置表格默认列宽度为15个字节
        sheet.setDefaultColumnWidth((short) 20);
        // 生成一个样式
        HSSFCellStyle style = workbook.createCellStyle();
        HSSFCellStyle style2 = getHssfCellStyle(workbook, style);
        // 产生表格标题行
        HSSFRow row = sheet.createRow(0);
        for (short i = 0; i < headers.length; i++) {
            HSSFCell cell = row.createCell(i);
            cell.setCellStyle(style);
            HSSFRichTextString text = new HSSFRichTextString(headers[i]);
            cell.setCellValue(text);
        }

        // 遍历集合数据，产生数据行
        Iterator<WmsOutboundTaskDTOForQuery> iterator = taskDTOForQueries.iterator();
        int index = 0;
        while (iterator.hasNext()) {
            index++;
            row = sheet.createRow(index);//创建行
            WmsOutboundTaskDTOForQuery next = iterator.next();
            //"车架号(VIN码)", "车型", "货主", "出库类型", "出库确认时间", "出库确认人", "物料代码", "配置", "颜色代码", "颜色"
            for (short i = 0; i < headers.length; i++) {
                HSSFCell cell = row.createCell(i);
                cell.setCellStyle(style2);
                switch (i) {
                    case 0: {
                        //"车架号(VIN码)"
                        cell.setCellValue(updateSetCellValue(next.getOtVin()));
                        break;
                    }
                    case 1: {
                        //"车型"
                        cell.setCellValue(updateSetCellValue(next.getOtVehicleSpecName()));
                        break;
                    }
                    case 2: {
                        //"物料代码"
                        cell.setCellValue(updateSetCellValue(next.getMaterialCode()));
                        break;
                    }
                    case 3: {
                        //"配置"
                        cell.setCellValue(updateSetCellValue(next.getConfiguration()));
                        break;
                    }
                    case 4: {
                        //"颜色代码"
                        cell.setCellValue(updateSetCellValue(next.getColourCode()));
                        break;
                    }
                    case 5: {
                        //"颜色"
                        cell.setCellValue(updateSetCellValue(next.getColourName()));
                        break;
                    }
                    case 6: {
                        //"货主"
                        cell.setCellValue(updateSetCellValue(next.getOtCustomerName()));
                        break;
                    }
                    case 7: {
                        //出库类型
                        OutBoundTaskTypeEnum byValue = OutBoundTaskTypeEnum.getByValue(updateSetCellValue(next.getOtType()));
                        cell.setCellValue(byValue != null ? byValue.getValue() : "");
                        break;
                    }
                    case 8: {
                        //"出库确认时间"
                        cell.setCellValue(updateSetCellValue(getFormatDate(next.getOtBlConfirmTime())));
                        break;
                    }
                    case 9: {
                        //"出库确认人"
                        cell.setCellValue(updateSetCellValue(next.getModifyUserName()));
                        break;
                    }
                    case 10: {
                        //"物流承运商"
                        cell.setCellValue(updateSetCellValue(next.getSpCarrier()));
                        break;
                    }
                    case 11: {
                        //"物流承运商"
                        cell.setCellValue(updateSetCellValue(next.getSpDealer()));
                        break;
                    }
                    default:
                        break;
                }
            }
        }
        return workbook;
    }

    private HSSFCellStyle getHssfCellStyle(HSSFWorkbook workbook, HSSFCellStyle style) {
        // 设置这些样式
        style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
        style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//上下居中
        style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style.setBorderTop(HSSFCellStyle.BORDER_THIN);
        style.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        // 生成一个字体
        HSSFFont font = workbook.createFont();
        font.setColor(HSSFColor.VIOLET.index);
        font.setFontHeightInPoints((short) 12);
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        // 把字体应用到当前的样式
        style.setFont(font);
        // 生成并设置另一个样式
        HSSFCellStyle style2 = workbook.createCellStyle();
        style2.setFillForegroundColor(HSSFColor.WHITE.index);
        style2.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        style2.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style2.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style2.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style2.setBorderTop(HSSFCellStyle.BORDER_THIN);
        style2.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        style2.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        // 生成另一个字体
        HSSFFont font2 = workbook.createFont();
        font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
        // 把字体应用到当前的样式
        style2.setFont(font2);
        return style2;
    }

    /**
     * @param title               标题
     * @param headers             表头
     * @param wmsOutboundTaskDTOS 参数列表
     * @param pattern             @Title exportExcel
     */
    private HSSFWorkbook updateExportToExcelForCQ(String title,
                                                  String[] headers,
                                                  List<WmsOutboundTaskDTOForQuery> wmsOutboundTaskDTOS,
                                                  String pattern) {
        // 声明一个工作薄
        HSSFWorkbook workbook = new HSSFWorkbook();
        // 生成一个表格
        HSSFSheet sheet = workbook.createSheet(title);
        // 设置表格默认列宽度为15个字节
        sheet.setDefaultColumnWidth((short) 20);
        // 生成一个样式
        HSSFCellStyle style = workbook.createCellStyle();
        HSSFCellStyle style2 = getHssfCellStyle(workbook, style);
        // 产生表格标题行
        HSSFRow row = sheet.createRow(0);
        for (short i = 0; i < headers.length; i++) {
            HSSFCell cell = row.createCell(i);
            cell.setCellStyle(style);
            HSSFRichTextString text = new HSSFRichTextString(headers[i]);
            cell.setCellValue(text);
        }

        // 遍历集合数据，产生数据行
        Iterator<WmsOutboundTaskDTOForQuery> iterator = wmsOutboundTaskDTOS.iterator();
        int index = 0;
        while (iterator.hasNext()) {
            index++;
            row = sheet.createRow(index);//创建行
            WmsOutboundTaskDTOForQuery next = iterator.next();
            //对应头  设置cell的值
            for (short i = 0; i < headers.length; i++) {
                HSSFCell cell = row.createCell(i);
                cell.setCellStyle(style2);
                //君马和重庆不一样的表头
                switch (i) {
                    case 0: {
                        cell.setCellValue(updateSetCellValue(next.getOtVin()));
                        break;
                    }
                    case 1: {
                        cell.setCellValue(updateSetCellValue(next.getOtVehicleSpecName()));
                        break;
                    }
                    case 2: {
                        cell.setCellValue(updateSetCellValue(next.getOtCustomerName()));
                        break;
                    }
                    case 3: {
                        //出库类型
                        OutBoundTaskTypeEnum byValue = OutBoundTaskTypeEnum.getByValue(updateSetCellValue(next.getOtType()));
                        cell.setCellValue(byValue != null ? byValue.getValue() : "");
                        break;
                    }
                    case 4: {
                        cell.setCellValue(updateSetCellValue(getFormatDate(next.getOtBlConfirmTime())));
                        break;
                    }
                    case 5: {
                        cell.setCellValue(updateSetCellValue(next.getModifyUserName()));
                        break;
                    }
                    case 6: {
                        if (StringUtils.isNotBlank(next.getOtOutboundFlag())) {
                            if (String.valueOf(WmsOutboundTaskOutboundFlagEnum.HAS_OUTBOUND.getValue()).equals(next.getOtOutboundFlag())) {
                                cell.setCellValue(WmsOutboundTaskOutboundFlagEnum.HAS_OUTBOUND.getText());
                            } else {
                                cell.setCellValue(WmsOutboundTaskOutboundFlagEnum.NOT_OUTBOUND.getText());
                            }
                        } else {
                            cell.setCellValue(WmsOutboundTaskOutboundFlagEnum.NOT_OUTBOUND.getText());
                        }
                        break;
                    }
                    case 7: {
                        if (next.getOtOutboundFlag1() != null) {
                            if (WmsOutboundTaskOutboundFlagEnum.HAS_OUTBOUND.getValue() == next.getOtOutboundFlag1()
                                    || WmsOutboundTaskOutboundFlagEnum.GATE_OUT.getValue() == (next.getOtOutboundFlag1())) {
                                cell.setCellValue(updateSetCellValue(getFormatDate(next.getInspectTime())));
                            }
                        }

                        break;
                    }
                    case 8: {
                        cell.setCellValue(updateSetCellValue(getFormatDate(next.getOtDepartureTime())));
                        break;
                    }
                    case 9: {
                        cell.setCellValue(updateSetCellValue(next.getSpCarrier()));
                        break;
                    }
                    default:
                        break;
                }
            }
        }
        return workbook;
    }

    /**
     * 出库记录条数
     *
     * @param dto 参数
     * @return 返回值
     */
    @Override
    public Integer countOutboundRecord(WmsOutboundImportExcelDTO dto) {
        logger.info("OutBoundTaskServiceImpl.countOutboundRecord param:{}", dto);
        //校验
        if (Objects.equals(dto, null))
            throw new BusinessException("传入参数为空!");
        if (StringUtils.isBlank(dto.getWhCode()))
            throw new BusinessException("仓库code不能为空!");
        if (StringUtils.isBlank(dto.getUserId()))
            throw new BusinessException("用户Id不能为空!");
        if (StringUtils.isBlank(dto.getOutConfirmEndTime())
                && StringUtils.isBlank(dto.getOutConfirmStartTime())) {
            throw new BusinessException("请选择出库起止时间");
        }
        HashMap<String, Object> paramMap = Maps.newHashMap();
        //用户填写了出库确认时间
        if (StringUtils.isNotBlank(dto.getOutConfirmStartTime())) {
            paramMap.put("startBlConfirmTime", dto.getOutConfirmStartTime() + " 00:00:00");
        }
        if (StringUtils.isNotBlank(dto.getOutConfirmEndTime())) {
            paramMap.put("endBlConfirmTime", dto.getOutConfirmEndTime() + " 23:59:59");
        }
        paramMap.put("otWhCode", dto.getWhCode());
        paramMap.put("otQuitFlag", TaskQuitFlagEnum.NOT_QUIT.getValue());//非退库标识
        paramMap.put("otStatus", WmsOutboundTaskStatusEnum.WMS_OUTBOUND_TASK_STATUS_FINISHED.getValue());
        paramMap.put("notDel", DeleteFlagEnum.NORMAL.getValue());//过滤已删除
        paramMap.put("orderByClause", "a.ot_id desc");
        if (StringUtils.isNotBlank(dto.getWhCode())) {
            if (WhCodeEnum.UNLCN_XN_CQ.getValue().equals(dto.getWhCode())) {
                return outboundTaskExtMapper.countOutboundRecordsForPage(paramMap);
            }
            if (WhCodeEnum.JM_CS.getValue().equals(dto.getWhCode())
                    || WhCodeEnum.JM_XY.getValue().equals(dto.getWhCode())) {
                //return outboundTaskExtMapper.countOutboundRecordsForPageJm(paramMap);
                paramMap.put("notChange", TaskIsNeedChangeEnum.NO_CHANGE.getCode());
                paramMap.put("cantChange", TaskIsNeedChangeEnum.NOT_CAR_TO_CHANGE.getCode());
                return outboundTaskExtMapper.countOutboundRecordsForPageJmWithNotice(paramMap);
            }
        }
        return null;
    }

    /**
     * 校验并返回参数
     *
     * @param dto 参数封装
     * @return 返回值
     */
    private Map<String, Object> getParamAndCheck(WmsOutboundImportExcelDTO dto) {
        if (Objects.equals(dto, null))
            throw new BusinessException("传入参数为空!");
        if (StringUtils.isBlank(dto.getWhCode()))
            throw new BusinessException("仓库code不能为空!");
        if (StringUtils.isBlank(dto.getUserId()))
            throw new BusinessException("用户Id不能为空!");
        if (StringUtils.isBlank(dto.getOutConfirmEndTime())
                && StringUtils.isBlank(dto.getOutConfirmStartTime())) {
            throw new BusinessException("请选择出库起止时间");
        }
        HashMap<String, Object> paramMap = Maps.newHashMap();
        //用户填写了出库确认时间
        if (StringUtils.isNotBlank(dto.getOutConfirmStartTime())) {
            paramMap.put("startBlConfirmTime", dto.getOutConfirmStartTime() + " 00:00:00");
        }
        if (StringUtils.isNotBlank(dto.getOutConfirmEndTime())) {
            paramMap.put("endBlConfirmTime", dto.getOutConfirmEndTime() + " 23:59:59");
        }
        paramMap.put("otWhCode", dto.getWhCode());
        paramMap.put("otQuitFlag", TaskQuitFlagEnum.NOT_QUIT.getValue());//非退库标识
        paramMap.put("otStatus", WmsPreparationPlanEnum.WMS_PLAN_FINISH.getValue());//状态已完成
        return paramMap;
    }

    /**
     * 判断字符串设置值--非空过滤
     *
     * @param object 参数
     * @return 返回
     */
    private String updateSetCellValue(Object object) {
        if (!Objects.equals(object, null)) {
            String value = object.toString();
            if (StringUtils.isNotBlank(value)) {
                return value;
            }
        }
        return "";
    }

    /**
     * 时间格式化--非空过滤
     */
    private String getFormatDate(Date date) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (date != null) {
            return sdf.format(date);
        }
        return "";
    }

    /**
     * 更新备料明细状态为已出库
     */
    private void updatePreparationDetails(SysUser sysUser, List<WmsPreparationVehicleDetail> wmsPreparationVehicleDetails) {
        if (CollectionUtils.isNotEmpty(wmsPreparationVehicleDetails)) {
            WmsPreparationVehicleDetail vehicleDetail = wmsPreparationVehicleDetails.get(0);
            vehicleDetail.setGmtUpdate(new Date());
            vehicleDetail.setVdOutstockStatus(String.valueOf(WmsOutboundStatusEnum.WMS_OUTBOUND_FINISH.getValue()));
            if (sysUser != null) {
                vehicleDetail.setModifyUserName(sysUser.getName());
            }
            wmsPreparationVehicleDetailMapper.updateByPrimaryKeySelective(vehicleDetail);
        }
    }

    /**
     * 释放库存
     */
    private void updateInventory(OutboundConfirmBO bo, SysUser sysUser, WmsInventoryLocation inventoryLocation) {
        Long invlocInvId = inventoryLocation.getInvlocInvId();
        WmsInventory wmsInventory = wmsInventoryMapper.selectByPrimaryKey(invlocInvId);
        if (!Objects.equals(wmsInventory, null)) {
            wmsInventory.setIsDeleted(DeleteFlagEnum.DELETED.getValue());
            wmsInventory.setGmtUpdate(new Date());
            wmsInventory.setModifyUserId(bo.getUserId());
            if (sysUser != null) {
                wmsInventory.setModifyUserName(sysUser.getName());
            }
            wmsInventoryMapper.updateByPrimaryKeySelective(wmsInventory);
        }
    }

    /**
     * 更新备料计划状态
     */
    private void updateOunboundTask(String vin) {
        //outboundtaskd
        if (StringUtils.isNotBlank(vin)) {
            WmsPreparationVehicleDetail updateDetail = new WmsPreparationVehicleDetail();
            updateDetail.setVdOutstockStatus(String.valueOf(WmsOutboundStatusEnum.WMS_OUTBOUND_FINISH.getValue()));

            WmsPreparationVehicleDetailExample selectExample = new WmsPreparationVehicleDetailExample();
            selectExample.createCriteria().andVdVinEqualTo(vin);
            vehicleDetailMapper.updateByExampleSelective(updateDetail, selectExample);

            List<WmsPreparationVehicleDetail> detailList = vehicleDetailMapper.selectByExample(selectExample);
            List<Long> idList = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(detailList)) {
                detailList.stream()
                        .filter(detail -> detail != null && detail.getVdPpId() != null)
                        .forEach(detail -> idList.add(detail.getVdPpId()));
            }
            //更新
            if (CollectionUtils.isNotEmpty(idList)) {
                WmsPreparationVehicleDetailExample idExample = new WmsPreparationVehicleDetailExample();
                idExample.createCriteria().andVdPpIdIn(idList);
                int count = vehicleDetailMapper.countByExample(idExample);
                if (count <= 0) {
                    WmsPreparationPlanExample planExample = new WmsPreparationPlanExample();
                    planExample.createCriteria().andPpIdIn(idList);

                    WmsPreparationPlan updatePlan = new WmsPreparationPlan();
                    updatePlan.setPpStatus(String.valueOf(WmsPreparationPlanEnum.WMS_PLAN_FINISH.getValue()));

                    wmsPreparationPlanMapper.updateByExampleSelective(updatePlan, planExample);
                }
            }
        }

    }

    /**
     * 释放 - 逻辑删除库位库存
     */
    private void deleteInventory(String vin) throws Exception {
        //getLocationByVin
        if (StringUtils.isNotBlank(vin)) {
            List<WmsInventoryLocation> locationList = wmsInventoryService.getLocationByVin(vin);

            List<Long> locationIdList = new ArrayList<>();
            List<Long> inventoryIdList = new ArrayList<>();

            if (CollectionUtils.isNotEmpty(locationList)) {
                locationList.stream()
                        .filter(location -> location != null)
                        .forEach(location -> {
                            if (location.getInvlocId() != null) {
                                locationIdList.add(location.getInvlocId());
                            }
                            if (location.getInvlocInvId() != null) {
                                inventoryIdList.add(location.getInvlocInvId());
                            }
                        });
            }

            //删除库存
            if (CollectionUtils.isNotEmpty(inventoryIdList)) {
                wmsInventoryService.deleteInventoryForBatch(inventoryIdList);
            }
            //删除库存对应商品库位
            if (CollectionUtils.isNotEmpty(locationIdList)) {
                wmsInventoryService.deleteLocationForBatch(locationIdList);
            }
        }
    }

    /**
     * 获取出入库记录数据
     */
    private WmsOutOfStorage getStorage(OutboundTaskConfirmFormBO taskConfirmFormBO, String whCode) throws Exception {
        WmsOutOfStorage storageInfo = null;
        //if (BarCodeTypeEnum.REPIR.getCode().equals(taskConfirmFormBO.getType())) {
        if (OrderHeadEnum.REPIR.getCode().equals(taskConfirmFormBO.getType())) {
            WmsInboundRepair repair = inboundRepairService.getWmsInboundRepairByVin(taskConfirmFormBO.getVin());
            if (repair == null) {
                throw new BusinessException("找不到对应的维修单数据");
            }
            inboundRepairService.updateInOutStatusByVin(taskConfirmFormBO.getVin(), RepairInOutStatusEnum.HAVE_SEND.getCode());
            storageInfo = createStorageInfo(taskConfirmFormBO.getVin(),
                    repair.getRpMaterialCode(), WmsOutOfStorageType.ZTYPE_OUTBOUND_Z3.getValue(),
                    "", null, whCode);
            storageInfo.setSerialNo(repair.getRpOutbillNo());
        }
        //借车单
        //if (BarCodeTypeEnum.BORROW.getCode().equals(taskConfirmFormBO.getType())) {
        if (OrderHeadEnum.BORROW.getCode().equals(taskConfirmFormBO.getType())) {
            WmsBorrowCarDetail carDetail = borrowCarService.getBorrowCarDetailByVin(taskConfirmFormBO.getVin());
            if (carDetail == null) {
                throw new BusinessException("找不到对应的借车单数据");
            }
            //更新为已出库
            borrowCarService.updateDetailStatusByVin(taskConfirmFormBO.getVin(), BorrowReturnEnum.NO_SEND.getCode());
            storageInfo = createStorageInfo(taskConfirmFormBO.getVin(),
                    carDetail.getBdMaterialCode(), WmsOutOfStorageType.ZTYPE_OUTBOUND_Z7.getValue(),
                    "", getRemarkForBorrow(carDetail), whCode);
            //storageInfo.setSerialNo(carDetail.getbd);
            WmsBorrowCar wmsBorrowCar = borrowCarService.getWmsBorrowCarById(carDetail.getBdBorrowId());
            if (wmsBorrowCar != null) {
                storageInfo.setSerialNo(wmsBorrowCar.getBcBorrowNo());//借车单号
            }
        }
        return storageInfo;
    }

    private String getRemarkForBorrow(WmsBorrowCarDetail carDetail) throws Exception {
        StringBuilder remark = new StringBuilder();
        if (carDetail.getBdBorrowId() != null) {
            WmsBorrowCar wmsBorrowCar = borrowCarService.getWmsBorrowCarById(carDetail.getBdBorrowId());
            if (wmsBorrowCar == null) {
                throw new BusinessException("找不到对应的借车单数据");
            }
            if (StringUtils.isNotBlank(wmsBorrowCar.getBcBorrowName())) {
                remark.append(wmsBorrowCar.getBcBorrowName());//借用人名字
                remark.append(", ");
            }
            if (StringUtils.isNotBlank(wmsBorrowCar.getBcBorrowDepartment())) {
                remark.append(wmsBorrowCar.getBcBorrowDepartment());//借用部门
                remark.append(", ");
            }
            if (StringUtils.isNotBlank(wmsBorrowCar.getBcBorrowTel())) {
                remark.append(wmsBorrowCar.getBcBorrowTel());//借用人电话
                remark.append(", ");
            }
        }
        if (remark.length() > 0) {
            return remark.substring(0, remark.lastIndexOf(","));
        }
        return remark.toString();
    }

    private WmsOutOfStorage createStorageInfo(String vin,
                                              String materCode,
                                              String type,
                                              String flag,
                                              String remark,
                                              String whCode) {
        WmsOutOfStorage storage = new WmsOutOfStorage();
        storage.setSernr(vin);//车架号
        storage.setMatnr(materCode);//物料编码
        storage.setZaction(WmsOutOfStorageAction.ACTION_OUTBOUND.getValue());//动作
        storage.setZtype(type);//业务类型
        storage.setBldat(new Date());//出入库日期
        //库存地点 - CS01-长沙 XY01-襄阳',
        if (WarehouseEnum.JM_XY.getWhCode().equals(whCode)) {
            storage.setUmlgo("XY01");
        }
        if (WarehouseEnum.JM_CS.getWhCode().equals(whCode)) {
            storage.setUmlgo("CS01");
        }

        storage.setSendStatus(SendStatusEnum.SEND_INIT.getValue());
        storage.setSendStatusSap(SendStatusEnum.SEND_INIT.getValue());
        return storage;
    }

    /**
     * 获取交接单信息
     */
    private HandoverDTO getHandoverDTO(List<WmsShipmentPlan> shipmentPlanList) throws Exception {
        WmsShipmentPlan shipmentPlan = shipmentPlanList.get(0);
        HandoverDTO handoverDTO = null;
        if (shipmentPlan != null) {
            handoverDTO = new HandoverDTO();
            handoverDTO.setWaybillNo(shipmentPlan.getHoHandoverNumber());//交接单号
            handoverDTO.setWhName(shipmentPlan.getSpWhName());//仓库
            if (StringUtils.isNotBlank(shipmentPlan.getSpGroupBoardNo())) {
                WmsPreparationPlan preparationPlan = wmsPreparationPlanService.getPreparationPlanByGroupDispNo(shipmentPlan.getSpGroupBoardNo());
                if (preparationPlan != null) {

                    handoverDTO.setEstimateLane(preparationPlan.getPpEstimateLane());//装车道
                }
            }
            //拼接省市区+详细地址
            String dest = getDest(shipmentPlan);
            handoverDTO.setDestAddress(dest);//收车地址
            handoverDTO.setType(getType(shipmentPlan.getSpDlvType()));//运输类型
            handoverDTO.setLogiPerson(shipmentPlan.getSpReceiveMan());//收货联系人
            handoverDTO.setLogiTel(shipmentPlan.getSpReceiveTel());//收货人联系电话
            handoverDTO.setDealeName(shipmentPlan.getSpDealerName());//经销商
            handoverDTO.setLogiName(shipmentPlan.getSpCarrier());//承运单位
            //handoverDTO.setTransportTime("");//运输期限yyyy.mm.dd - 暂时没有
            //handoverDTO.setVehiclePlate("");//承运车牌 - 暂时没有
            //handoverDTO.setDriver("");//承运司机
            //handoverDTO.setDriverTel("");//司机电话
        }
        Map<String, String> map = new HashMap<>();
        StringBuilder driverBuilder = new StringBuilder();
        StringBuilder driverTelBuilder = new StringBuilder();
        shipmentPlanList.stream()
                .filter(sp -> sp != null
                        && StringUtils.isNotBlank(sp.getSpLogiContact())
                )
                .forEach(sp -> {
                    String contact = map.get(sp.getSpLogiContact());
                    if (StringUtils.isBlank(contact)) {
                        driverBuilder.append(sp.getSpLogiContact());
                        driverBuilder.append(" ");
                        String tel = sp.getSpLogiPhone();
                        if (StringUtils.isNotBlank(tel)) {
                            map.put(sp.getSpLogiContact(), tel);
                            driverTelBuilder.append(tel);
                            driverTelBuilder.append(" ");
                        }
                    }
                });
        if (StringUtils.isNotBlank(driverBuilder)) {
            handoverDTO.setDriver(driverBuilder.toString());
        }
        if (StringUtils.isNotBlank(driverTelBuilder)) {
            handoverDTO.setDriverTel(driverTelBuilder.toString());
        }
        return handoverDTO;
    }

    /**
     * 拼接收货地址
     */
    private String getDest(WmsShipmentPlan shipmentPlan) {
        StringBuilder destStr = new StringBuilder();
        //省份
        if (StringUtils.isNotBlank(shipmentPlan.getSpProvince())) {
            destStr.append(shipmentPlan.getSpProvince());
        }
        //市
        if (StringUtils.isNotBlank(shipmentPlan.getSpCity())) {
            destStr.append(shipmentPlan.getSpCity());
        }
        //县
        if (StringUtils.isNotBlank(shipmentPlan.getSpDistrictCounty())) {
            destStr.append(shipmentPlan.getSpDistrictCounty());
        }
        //详细地址
        if (StringUtils.isNotBlank(shipmentPlan.getSpDetailedAddress())) {
            destStr.append(shipmentPlan.getSpDetailedAddress());
        }
        return destStr.toString();
    }

    /**
     * 判断发货类型
     */
    private String getType(String type) {
        if (DispatchTypeEnum.A1.getCode().equals(type)) {
            return "正常发货";
        }
        if (DispatchTypeEnum.A2.getCode().equals(type)) {
            return "调拨发货";
        }
        return null;
    }

    /**
     * 获取数据
     * <p>
     * 2018-5-10 入库通知单重构,修复交接单打印数据获取-->wms_wareHouse_notice_detail
     * </p>
     */
    private void saveHandoverDetailInfo(WmsPreparationVehicleDetail detail,
                                        HandoverDetailDTO dto,
                                        List<WmsShipmentPlan> shipmentPlanList) {
        HashMap<String, String> storeConfiguration = Maps.newHashMap();
        for (WmsShipmentPlan sp : shipmentPlanList) {
            if (StringUtils.isBlank(storeConfiguration.get(sp.getSpMaterialCode()))) {
                storeConfiguration.put(sp.getSpMaterialCode(), sp.getSpConfigure());
            }
        }
        if (StringUtils.isNotBlank(detail.getVdVin())) {
            dto.setVin(detail.getVdVin());
            //车型描述  2018-1-19 bugfix 取asn表中的数据
            //dto.setStyleDesc(detail.getVdVehicleDesc());
            //获取asn数据
            WmsWarehouseNoticeDetailExample detailExample = new WmsWarehouseNoticeDetailExample();
            detailExample.createCriteria().andWndWarehouseCodeEqualTo(shipmentPlanList.get(0).getSpWhCode())
                    .andWndVinEqualTo(detail.getVdVin());
            detailExample.setOrderByClause("wnd_id desc");
            detailExample.setLimitStart(0);
            detailExample.setLimitEnd(1);
            List<WmsWarehouseNoticeDetail> noticeDetails = wmsWarehouseNoticeDetailMapper.selectByExample(detailExample);
            //WmsAsnTempExample example = new WmsAsnTempExample();
            //example.createCriteria().andAtVinEqualTo(detail.getVdVin());
            //List<WmsAsnTemp> asnTempList = wmsAsnTempMapper.selectByExample(example);
            if (CollectionUtils.isNotEmpty(noticeDetails)) {
                WmsWarehouseNoticeDetail noticeDetail = noticeDetails.get(0);
                //WmsShipmentPlan wmsShipmentPlan = shipmentPlanList.get(0);
                if (noticeDetail != null) {
                    dto.setBrand(StringUtils.substringBefore(storeConfiguration.get(noticeDetail.getWndMaterialCode()), ";"));
                    dto.setEngineNo(noticeDetail.getWndEngineNo());//发动机编码
                    dto.setSign("");//签收
                    dto.setStyleCode(noticeDetail.getWndMaterialCode());  //物料代码
                    //2018-1-19 bugfix 修复打印交接单不显示物料描述(描述信息:物料名称,颜色)
                    String materialName = noticeDetail.getWndMaterialName();
                    String atCarColour = noticeDetail.getWndColorName();
                    if (StringUtils.isNotBlank(materialName)) {
                        if (StringUtils.isNotBlank(atCarColour)) {
                            dto.setStyleDesc(materialName + ", " + atCarColour);
                        }
                    }
                    dto.setColor(atCarColour);//颜色
                }
            }
        }
    }

    /**
     * 物料编码
     */
    private String getMaterCode(Long ppId) {
        if (ppId != null) {
            WmsPreparationPlan preparationPlan = wmsPreparationPlanMapper.selectByPrimaryKey(ppId);
            if (preparationPlan != null) {
                return preparationPlan.getPpMaterialCode();
            }
        }
        return null;
    }
}
